1601. 最多可达成的换楼请求数目题解
题目来源:1601. 最多可达成的换楼请求数目
2022.02.28每日一题
每日一题专栏地址:LeetCode 每日一题题解更新中❤️💕
今天是一道困难,
题目的大意是交换房间,使最后各个房间的人数不变
换句话说就是找环
就拿第一个例子来说,requests
数组是[[0,1],[1,0],[0,1],[1,2],[2,0],[3,4]]
能围成环的有[0,1],[1,0]
与[0,1],[1,2],[2,0]
,
因此这五个即是本例子的答案
法一:DFS搜索(回溯)
本题目的数据范围不大,在1 <= n <= 20
和1 <= requests.length <= 16
,使用DFS不会超时,
首先创建一共数组condition
统计各个房子迁入/迁出的人数
创建一个变量来统计满足要求的最大数量
每次只需要统计condition
是否全为 0
,就可以判断是否形成了一个环
形成环则满足要求,与当前的值进行比较,取最大值
若不满足,则结束
为了避免每次统计condition
数组需要遍历,浪费时间,可以定义一个变量 zero
来判断是否全为0 ,若 condition[x]
在增加或者减少前为 0
则减一,如果 condition[x]
在增加或者减少后为 0
则加一
这样就免去了每次遍历condition
数组的麻烦,优化了效率
具体代码以及注释如下
class Solution {
public:
int cnt = 0, zero = 0, res = 0, n;
vector<int> condition;
int maximumRequests(int n, vector<vector<int>> &requests) {
this->n = n;
zero = n;
condition = vector(n, 0);
dfs(requests, 0);
return res;
}
void dfs(vector<vector<int>> &requests, int pos) {
// 如果 pos 与 request 的大小相等说明已经全部搜寻过了
if (pos == requests.size()) {
// 如果此时,zero 的数目与 楼房数目 n 相等,则说明全部都成环
if (zero == n)
// 则取最大值
res = max(res, cnt);
// 结束递归
return;
}
// 不选择 pos 点的情况
dfs(requests, pos + 1);
// 选择 pos 的情况
// 选择一个临时变量来记录 zero 的数量,以便后续进行回溯
int z = zero;
// 运行一次,cnt 统计的值加一
cnt++;
vector<int> &r = requests[pos];
int x = r[0], y = r[1];
// 如果condition[x] == 0,说明搬出前condition[x] = 0,zero 需要减一
zero -= (condition[x] == 0);
condition[x]--;
// 如果condition[x] == 0,说明搬出后condition[x] = 0,zero 需要加一
zero += (condition[x] == 0);
// 如果condition[y] == 0,说明搬入前condition[y] = 0,zero 需要减一
zero -= (condition[y] == 0);
condition[y]++;
// 如果condition[y] == 0,说明搬入后condition[y] = 0,zero 需要加一
zero += (condition[y] == 0);
dfs(requests, pos + 1);
condition[x]++;
condition[y]--;
zero = z;
cnt--;
}
};
class Solution {
int cnt = 0, zero = 0, res = 0, n;
int[] condition;
public int maximumRequests(int n, int[][] requests) {
this.n = n;
zero = n;
condition = new int[n];
dfs(requests, 0);
return res;
}
void dfs(int[][] requests, int pos) {
// 如果 pos 与 request 的大小相等说明已经全部搜寻过了
if (pos == requests.length) {
// 如果此时,zero 的数目与 楼房数目 n 相等,则说明全部都成环
if (zero == n)
// 则取最大值
res = Math.max(res, cnt);
// 结束递归
return;
}
// 不选择 pos 点的情况
dfs(requests, pos + 1);
// 选择 pos 的情况
// 选择一个临时变量来记录 zero 的数量,以便后续进行回溯
int z = zero;
// 运行一次,cnt 统计的值加一
cnt++;
int[] r = requests[pos];
int x = r[0], y = r[1];
// 如果condition[x] == 0,说明搬出前condition[x] = 0,zero 需要减一
zero -= (condition[x] == 0 ? 1 : 0);
condition[x]--;
// 如果condition[x] == 0,说明搬出后condition[x] = 0,zero 需要加一
zero += (condition[x] == 0 ? 1 : 0);
// 如果condition[y] == 0,说明搬入前condition[y] = 0,zero 需要减一
zero -= (condition[y] == 0 ? 1 : 0);
condition[y]++;
// 如果condition[y] == 0,说明搬入后condition[y] = 0,zero 需要加一
zero += (condition[y] == 0 ? 1 : 0);
dfs(requests, pos + 1);
condition[x]++;
condition[y]--;
zero = z;
cnt--;
}
};