leetcode每日一题
7月
1833. 雪糕的最大数量
5801. 消灭怪物的最大数量
1418. 点菜展示表
1711. 大餐计数
5792. 统计平方和三元组的数目
274. H 指数
面试题 10.02. 变位词组
6月
1744. 你能在你最喜欢的那天吃到你最喜欢的糖果吗?
42. 接雨水
206. 反转链表
234. 回文链表
141. 环形链表
474. 一和零
5777. 使数组元素相等的减少操作次数
5776. 判断矩阵经轮转后是否一致
1897. 重新分配字符使所有字符串都相等
752. 打开转盘锁
5781. 删除一个字符串中所有出现的给定子字符串
5789. 你完成的完整对局数
5788. 字符串中的最大奇数
852. 山脉数组的峰顶索引
1894. 找到需要补充粉笔的学生编号
5786. 可移除字符的最大数目
1893. 检查是否区域内所有整数都被覆盖
1899. 合并若干三元组以形成目标三元组
5799. 最美子字符串的数目
5780. 删除一个元素使数组严格递增
5月
342. 4的幂
231. 2 的幂
560. 和为K的子数组
141. 环形链表
1074. 元素和为目标值的子矩阵数量
461. 汉明距离
1190. 反转每对括号间的子串
664. 奇怪的打印机
1787. 使所有区间的异或结果为零(放弃治疗)
1707. 与数组中元素的最大异或值
810. 黑板异或游戏
1035. 不相交的线
692. 前K个高频单词
1738. 找出第 K 大的异或坐标值
993. 二叉树的堂兄弟节点
13. 罗马数字转整数
1442. 形成两个异或相等数组的三元组数目
12. 整数转罗马数字
1269. 停在原地的方案数
1734. 解码异或后的排列
1310. 子数组异或查询
872. 叶子相似的树
vditor使用说明
645. 错误的集合
930. 和相同的二元子数组
5793. 迷宫中离入口最近的出口
5843. 作为子字符串出现在单词中的字符串数目
5832. 构造元素不等于两相邻元素平均值的数组
5851. 找出不同的二进制字符串
5850. 找出数组的最大公约数
5835. 最大方阵和
n个人匹配,两两匹配,匹配多轮
本文档使用 MrDoc 发布
-
+
首页
n个人匹配,两两匹配,匹配多轮
## 要求 要求 n 个人匹配,如果是奇数则有一人轮空,两两匹配,匹配多轮,每轮要求不能和上轮匹配对象重复,优先选择匹配次数少的(满足其他成员的情况下)。 不能重复:如第一轮 1 2 匹配,则下一轮 1 不能与 2 匹配 优先次数少:比如 1234,第一轮 1 2 匹配,则 1 与 2 匹配次数为 1 次,1 与 3,1 与 4 为 0 次,则优先匹配 3,4 特殊情况:3 只能被 2 选择,那 1 只能选择 4 第 1 轮 1-2 3-4 第 2 轮 1-3 2-4 第 3 轮 1-4 2-3 第 3 轮 1-2 3-4 第 4 轮,跟上面第 2 轮一样 ## 代码 ```js function test(nums) { const map = {}; const length = nums.length; // 初始化数据 // 第二个数字是匹配次数 // 处理为 {'1': { '2': 0, '3': 0, '4': 0 }} for (let i = 0; i < length; i++) { for (let j = 0; j < length; j++) { if (i !== j) { const tmp = map[nums[i]] || {}; tmp[nums[j]] = 0; map[nums[i]] = tmp; } } } // console.log(map); // 轮次 let CNT = 0; // 上一轮匹配结果 let lastSet = new Set(); while (CNT++ < 10000) { let res = []; // 直到找到结果 while (res.length < Math.floor(nums.length / 2)) { res = []; // 记录已经匹配的 id const dead = new Set(); // 当前轮次的匹配情况 const currentSet = new Set(); for (let i = 0; i < length; i++) { // 已经找过 if (dead.has(nums[i])) continue; // 匹配次数相同的,随机打乱顺序 // Object.entries(map[nums[i]]) 将对象转成数组 // 如 { '2': 0, '3': 0, '4': 0 } 转成 [[2,0],[3,0],[4,0]] const arr = Object.entries(map[nums[i]]).sort((a, b) => { // 相同就随机打乱 if (a[1] === b[1]) { return Math.random() - 0.5; } return a[1] - b[1]; }); // 轮询匹配 for (let [node, count] of arr) { // 转成数字 node = Number(node); // 说明被选走 跳过 if (dead.has(node)) continue; // 跟上次匹配一样 跳过 if (lastSet.has([nums[i], node].sort((a, b) => a - b).join())) continue; // 匹配结果 res.push([nums[i], node]); // 加入到已经匹配过的集合 dead.add(nums[i]) dead.add(node); // 匹配次数 +1 map[nums[i]][node]++; map[node][nums[i]]++; // 当前匹配的 currentSet.add([nums[i], node].sort((a, b) => a - b).join()); break; } } lastSet = currentSet; } // if (res.length !== 4) { console.log(` 第 ${String(CNT)}轮 `, lastSet, res); // } } } // nums = [1, 2, 3, 4] // nums = [1, 2, 3, 4, 5, 6] nums = [1, 2, 3, 4, 5, 6, 7, 8] // nums = []; // for(let i=1;i<=1000;i++){ // nums.push(i); // } console.log(test(nums)); ``` 新的 ```js // 用循环 // function test(nums) { // const map = {}; // const length = nums.length; // // 初始化数据 // // 第二个数字是匹配次数 // // 处理为 {'1': { '2': 0, '3': 0, '4': 0 }} // for (let i = 0; i < length; i++) { // for (let j = 0; j < length; j++) { // if (i !== j) { // const tmp = map[nums[i]] || {}; // tmp[nums[j]] = 0; // map[nums[i]] = tmp; // } // } // } // // console.log(map); // console.log('================='); // // 轮次 // let CNT = 0; // // 上一轮匹配结果 // let lastSet = new Set(); // while (CNT++ < 1) { // if (CNT % 7 === 0) { // lastSet = new Set(); // for (let i = 0; i < length; i++) { // for (let j = 0; j < length; j++) { // if (i !== j) { // const tmp = map[nums[i]] || {}; // tmp[nums[j]] = 0; // map[nums[i]] = tmp; // } // } // } // } // let res = []; // // 直到找到结果 // while (res.length < Math.floor(nums.length / 2)) { // res = []; // // 记录已经匹配的id // const dead = new Set(); // // 当前轮次的匹配情况 // const currentSet = new Set(); // for (let i = 0; i < length; i++) { // // 已经找过 // if (dead.has(nums[i])) continue; // // 匹配次数相同的,随机打乱顺序 // // Object.entries(map[nums[i]]) 将对象转成数组 // // 如 { '2': 0, '3': 0, '4': 0 } 转成 [[2,0],[3,0],[4,0]] // const arr = Object.entries(map[nums[i]]).sort((a, b) => { // // 相同就随机打乱 // if (a[1] === b[1]) { // return Math.random() - 0.5; // } // return a[1] - b[1]; // }); // // console.log(nums[i],' ',arr.map(item=>`${item[0]}:${item[1]}`).toString()); // // 轮询匹配 // for (let [node, count] of arr) { // // 转成数字 // node = Number(node); // // 说明被选走 跳过 // if (dead.has(node)) continue; // // 跟上次匹配一样 跳过 // if (lastSet.has([nums[i], node].sort((a, b) => a - b).join())) continue; // // 匹配结果 // res.push([nums[i], node]); // // 加入到已经匹配过的集合 // dead.add(nums[i]) // dead.add(node); // // 匹配次数+1 // map[nums[i]][node]++; // map[node][nums[i]]++; // // 当前匹配的 // currentSet.add([nums[i], node].sort((a, b) => a - b).join()); // break; // } // } // // console.log(CNT,lastSet,res); // lastSet = currentSet; // console.log(`第${CNT}轮`, map); // } // // if (res.length !== 4) { // // console.log(`第${String(CNT)}轮`, lastSet, res); // // } // } // } // 回溯 function test(nums) { const map = {}; const numCnt = {}; const length = nums.length; // 初始化数据 // 第二个数字是匹配次数 // 处理为 {'1': { '2': 0, '3': 0, '4': 0 }} for (let i = 0; i < length; i++) { for (let j = 0; j < length; j++) { if (i !== j) { const tmp = numCnt[nums[i]] || {}; tmp[nums[j]] = 0; numCnt[nums[i]] = tmp; const tmp2 = map[nums[i]] || []; tmp2.push(nums[j]); map[nums[i]] = tmp2; } } } // console.log(map); console.log('================='); // 轮次 let CNT = 0; // 上一轮匹配结果 let lastSet = new Set(); while (CNT++ < 1) { // if (CNT % 7 === 0) { // lastSet = new Set(); // for (let i = 0; i < length; i++) { // for (let j = 0; j < length; j++) { // if (i !== j) { // const tmp = map[nums[i]] || {}; // tmp[nums[j]] = 0; // map[nums[i]] = tmp; // } // } // } // } let res = []; // 先将匹配次数都进行排序 for (let i = 0; i < length; i++) { map[nums[i]].sort((a, b) => { // 相同就随机打乱 if (numCnt[nums[i]][a] === numCnt[nums[i]][b]) { return Math.random() - 0.5; } return numCnt[nums[i]][a] - numCnt[nums[i]][b]; }); } const result = []; const dfs = (nums, k, dead, data, hasDead) => { if (k === nums.length - 4) { if (data.size === 4) { result.push(Array.from(data).sort((a, b) => { if (a[0] === b[0]) { return a[1] - b[1]; } return a[0] - b[0]; })); } data.clear(); return; } for (let i = k; i < nums.length; i++) { // 已经找过 if (dead.has(nums[i])) continue; const num = nums[i]; dead.add(num); let nextNode; // 轮询匹配 for (let node of map[nums[i]]) { // 说明被选走 跳过 if (dead.has(node)) continue; // 跟上次匹配一样 跳过 // if (lastSet.has([nums[i], node].sort((a, b) => a - b).join())) continue; // 匹配结果 data.add([nums[i], node].sort((a,b)=>a-b)); // 加入到已经匹配过的集合 nextNode = node; // 匹配次数+1 // numCnt[nums[i]][node]++; // numCnt[node][nums[i]]++; // 当前匹配的 // currentSet.add([nums[i], node].sort((a, b) => a - b).join()); // 符合条件就结束 // break; // 开始下一位 dead.add(nextNode); // dead.add(num); // dead.add(nums[i]); [nums[k], nums[i]] = [nums[i], nums[k]]; dfs(nums, k + 1, dead, data, hasDead); // 交换回去,再删了原来的值 [nums[k], nums[i]] = [nums[i], nums[k]]; // data.delete([nums[i], node].sort((a,b)=>a-b)); // dead.delete(nextNode); // dead.delete(nums); // dead.delete(nums[i]); } // dead.delete(num); } } // 记录已经匹配的id const dead = new Set(); // 当前轮次的匹配情况 const currentSet = new Set(); dfs(nums, 0, dead, new Set(), new Set()) lastSet = currentSet; // console.log(CNT,lastSet,res); // console.log(`第${CNT}轮`, map); // if (res.length !== 4) { console.log(`第${String(CNT)}轮`, result.sort((a,b)=>{ if(a[0][0]===b[0][0]){ return a[0][1]-b[0][1]; } return a[0][0]-b[0][0]; })); // console.log(`第${String(CNT)}轮`, res); // } } } nums = [1, 2, 3, 4, 5, 6, 7, 8] // nums = [1, 2, 3, 4, 5, 6] // nums = [1, 2, 3, 4] // nums = []; // for(let i=1;i<=1000;i++){ // nums.push(i); // } console.log(test(nums)); ```
czbiao
2022年8月16日 08:38
转发文档
收藏文档
上一篇
下一篇
手机扫码
复制链接
手机扫一扫转发分享
复制链接
阅读量
次
本站总访问量
次
本站访客数
人次
Markdown文件
分享
链接
类型
密码
更新密码