本篇内容:leetcode每日一题 1601. 最多可达成的换楼请求数目 二进制枚举(状态压缩)
文章专栏:leetcode每日一题《打卡日常》
最近更新:2022年2月25日 leetcode每日一题 2016. 增量元素之间的最大差值 简单模拟 一题三解两做~
个人简介:一只二本院校在读的大三程序猿,本着注重基础,打卡算法,分享技术作为个人的经验总结性的博文博主,虽然可能有时会犯懒,但是还是会坚持下去的,如果你很喜欢博文的话,建议看下面一行~(疯狂暗示QwQ)
点赞 收藏 ⭐留言 一键三连 关爱程序猿,从你我做起
新学期,新气象,开学第一天,二月最后一天,果然是困难题呀,不过小付也为了加深思维学习,励志争取看懂每一道力扣的困难题解来加深思维,扩展算法思想,就酱紫吧,冲冲冲,也为以后AC一场周赛做准备。
我们有
n
栋楼,编号从0 到 n - 1
。每栋楼有若干员工。由于现在是换楼的季节,部分员工想要换一栋楼居住。
给你一个数组 requests ,其中
requests[i] = [fromi, toi]
,表示一个员工请求从编号为fromi 的楼搬到编号为 toi 的楼
。
一开始 所有楼都是满的,所以从请求列表中选出的若干个请求是可行的需要满足 每栋楼员工净变化为 0 。意思是每栋楼
离开
的员工数目等于
该楼搬入
的员工数数目。比方说n = 3
且两个员工要离开楼 0 ,一个员工要离开楼 1 ,一个员工要离开楼 2 ,如果该请求列表可行,应该要有两个员工搬入楼 0 ,一个员工搬入楼 1 ,一个员工搬入楼 2 。
请你从原请求列表中选出若干个请求,使得它们是一个可行的请求列表,并返回所有可行列表中最大请求数目。
输入: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 个请求。
输入: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
本题考查知识点
三叶姐姐
的思路:二进制枚举(状压)来进行求解的
,这里我们假设共有 m
个人提出请求,m = requests.length
我们可以知道对于每个人请求都是有两种状态的,接受 / 不接受
更换宿舍的请求 , 接受 / 不接受
当前请求对于其他人的请求
也是相互独立开来
的 ,换句话说 每个人 有 2 种状态
,但是m个人就有 2 ^ m
种状态。 我们默认 当前状态在二进制中表示末位为1时 ,则认为接受了请求, 这样一来呢,我们很清楚的就知道了 对于一个状态而言 它对应二进制中 1 的个数就代表了我们的当前状态下 接受了请求的个数
。理解了上述,对于这道题就成功了一大半了,剩下就是对思路的实现。二进制模拟(状态压缩)
class Solution {
public int maximumRequests(int n, int[][] requests) {
// 获取提出更换请求的员工个数
int m = requests.length;
// max 代表的是员工的状态 -----> 员工请求的请求可以被接受 / 不接受 每个员工有两种状态 那么就有 2^m 次种状态结果
int maxStatus = 1 << m, res = 0;
// 记录是否成功接受请求的数组
int[] netChangeArr = new int[n];
// 枚举所有状态,二进制中 1 的个数为当前状态的请求个数
for (int i = 0; i < maxStatus; i++) {
int[] tmp = new int[n];
int state = i;
// 用于记录当前的员工请求下标
int idx = 0;
// 用于记录当前状态下的接受的请求个数
int cnt = 0;
// 用于获取当前状态中二进制数字中1的个数
while (state > 0) {
// 判断最后一位是否为1
int isAccept = state & 1;
// 如果为 1 则说明了当前状态被接受了 需要记录住房情况
if (isAccept == 1) {
// 获取需要从哪里 搬到 哪里的位置信息
int from = requests[idx][0];
int to = requests[idx][1];
// 记录住房净变化
tmp[from]--;
tmp[to]++;
cnt++;
}
// 获取前一个员工的状态请求情况
state >>= 1;
idx++;
}
// 根据我们上面完成得到记录住房变化 需要满足每栋楼员工净变化为 0
// 滚动获取最大值
if (Arrays.equals(tmp, netChangeArr)) {
res = Math.max(res,cnt);
}
}
return res;
}
}
2022-2-28今天小付打卡了哦~
美好的日出 美好的山河
都因有你存在 而璀璨 耀眼