LeetCode-1601 最多可达成的换楼请求数目

简介: LeetCode-1601 最多可达成的换楼请求数目

来源:力扣(LeetCode)

链接:https://leetcode-cn.com/problems/maximum-number-of-achievable-transfer-requests

题目描述

我们有 n 栋楼,编号从 0 到 n - 1 。每栋楼有若干员工。由于现在是换楼的季节,部分员工想要换一栋楼居住。

给你一个数组 requests ,其中 requests[i] = [fromi, toi] ,表示一个员工请求从编号为 fromi 的楼搬到编号为 toi 的楼。

一开始 所有楼都是满的,所以从请求列表中选出的若干个请求是可行的需要满足 每栋楼员工净变化为 0 。意思是每栋楼 离开 的员工数目 等于 该楼 搬入 的员工数数目。比方说 n = 3 且两个员工要离开楼 0 ,一个员工要离开楼 1 ,一个员工要离开楼 2 ,如果该请求列表可行,应该要有两个员工搬入楼 0 ,一个员工搬入楼 1 ,一个员工搬入楼 2 。

请你从原请求列表中选出若干个请求,使得它们是一个可行的请求列表,并返回所有可行列表中最大请求数目。

 

示例 1:

 

 

输入:n = 5, requests = [[0,1],[1,0],[0,1],[1,2],[2,0],[3,4]]
输出:5

解释:请求列表如下:

从楼 0 离开的员工为 x 和 y ,且他们都想要搬到楼 1 。

从楼 1 离开的员工为 a 和 b ,且他们分别想要搬到楼 2 和 0 。

从楼 2 离开的员工为 z ,且他想要搬到楼 0 。

从楼 3 离开的员工为 c ,且他想要搬到楼 4 。

没有员工从楼 4 离开。

我们可以让 x 和 b 交换他们的楼,以满足他们的请求。

我们可以让 y,a 和 z 三人在三栋楼间交换位置,满足他们的要求。

所以最多可以满足 5 个请求。

示例 2:

 

 

输入:n = 3, requests = [[0,0],[1,2],[2,1]]
输出:3

解释:请求列表如下:

从楼 0 离开的员工为 x ,且他想要回到原来的楼 0 。

从楼 1 离开的员工为 y ,且他想要搬到楼 2 。

从楼 2 离开的员工为 z ,且他想要搬到楼 1 。

我们可以满足所有的请求。

示例 3:

输入:n = 4, requests = [[0,3],[3,1],[1,2],[2,0]]
输出:4

 

提示:

1 <= n <= 20
1 <= requests.length <= 16
requests[i].length == 2
0 <= fromi, toi < n

解题思路

一道很常规的枚举回溯题。每个请求有两种状态,允许或者不允许,依次枚举每一种情况,然后判断此情况下每栋楼人员变动是否持平,如果持平就比较请求数目是否大于之前的最大值。

需要注意的是判断条件十分严苛,vector形参不加入引用会导致无数次拷贝,会超时,手动还原状态并且选择引用vector时间会少很多。

并且判断每栋楼变动是否持平并不需要每次遍历数组,而是可以维护一个持平的计数,这样可以省去每次遍历vector。

代码展示

 

class Solution {
public:
    int iN;
    int dfs(int &iMax, vector<int> &viPerson, vector<vector<int>> &requests, int iIndex, int iCount, int iZero)
    {
        if(iIndex >= requests.size())
            return 0;
        dfs(iMax, viPerson, requests, iIndex +1, iCount, iZero);
        iZero +=  (viPerson[requests[iIndex][0]] == 0);
        --viPerson[requests[iIndex][0]];
        iZero -=  (viPerson[requests[iIndex][0]] == 0);
        iZero +=  (viPerson[requests[iIndex][1]] == 0);
        ++viPerson[requests[iIndex][1]];
        iZero -=  (viPerson[requests[iIndex][1]] == 0);
        iCount++;
        if(iZero == iN && iCount > iMax)
        {
            iMax = iCount;
        }
        dfs(iMax, viPerson, requests, iIndex +1, iCount, iZero);
        ++viPerson[requests[iIndex][0]];
        --viPerson[requests[iIndex][1]];
        iCount--;
        return 0;
    }
    int maximumRequests(int n, vector<vector<int>>& requests) {
        int iZero = n;
        iN = n;
        vector<int> viPerson(n, 0);
        int iMax = 0;
        dfs(iMax, viPerson, requests, 0, 0, iZero);
        return iMax;
    }
};

运行结果

 

相关文章
|
6月前
|
算法 测试技术 C#
区间合并|LeetCode2963:统计好分割方案的数目
区间合并|LeetCode2963:统计好分割方案的数目
|
4月前
|
存储 算法
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
经典的滑动窗口的题目 力扣 2799. 统计完全子数组的数目(面试题)
|
4月前
2670.找出不同元素数目差数组-力扣(LeetCode)
2670.找出不同元素数目差数组-力扣(LeetCode)
32 0
|
6月前
[leetcode~数位动态规划] 2719. 统计整数数目 hard
[leetcode~数位动态规划] 2719. 统计整数数目 hard
|
6月前
|
算法
"刷题记录:哈希表+双指针 | leetcode-2465. 不同的平均值数目 "
该文段是一篇关于编程题目的解答,主要讨论如何找到数组中所有不同平均值的个数。作者首先使用排序和哈希集来解决,将数组转为列表排序后,通过双指针计算平均值并存入哈希集以去重。然后,作者发现可以优化方案,通过双指针在排序后的数组中直接计算两数之和,用哈希集记录不重复的和,从而避免实际计算平均值,提高了算法效率。最终代码展示了这两种方法。
55 0
|
6月前
|
算法 测试技术 C#
【图论】【分类讨论】LeetCode3017按距离统计房屋对数目
【图论】【分类讨论】LeetCode3017按距离统计房屋对数目
|
6月前
|
存储
leetcode2744. 最大字符串配对数目
leetcode2744. 最大字符串配对数目
32 0
|
6月前
|
Serverless
leetcode2719. 统计整数数目
leetcode2719. 统计整数数目
45 0
|
6月前
|
算法 测试技术 C#
LeetCode2444: 统计定界子数组的数目
LeetCode2444: 统计定界子数组的数目
|
6月前
|
算法 机器人 测试技术
二分查找|双指针:LeetCode:2398.预算内的最多机器人数目
二分查找|双指针:LeetCode:2398.预算内的最多机器人数目