解题过程
:::info
题目链接
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。
:::
/*** @link https://leetcode.cn/problems/set-mismatch/* @title 645. 错误的集合* @description 集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。* 给定一个数组 nums 代表了集合 S 发生错误后的结果。* 请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回* @param {number[]} nums* @return {number[]}*/// 解法一:// var findErrorNums = function (nums) {// nums.sort((a, b) => a - b)// console.log(nums)// for (let i = 0; i < nums.length; i++) {// if (nums[i] === nums[i + 1]) {// // const minNums = nums.find(i => i !== nums[i])// if (nums[i] === 1) {// return [nums[i], nums[i + 1]]// } else if (nums[i] === 2) {// return [nums[i], 1]// }// // return [nums[i], Math.max(1, nums[i] - 1, nums[i] + 1)]// }// }// }// 解法二:穷举所有遇到的情况判断处理,结果失败// 不考虑排序,直接遍历数组nums, 判断当前索引项跟下一个索引项是否相同// 相同则记录当前值和下一个被重复的值 + 1 就是丢失的值❌,因为重复的值不一定就是相邻的数字,比如[ 2, 3, 4, 4, 5 , 7 ],重复的数字是4,但丢失的数字缺不是5// 暂不考虑数组排序问题,默认有小到大排好序// var findErrorNums = function (nums) {// const res = []// for (let i = 0; i < nums.length; i++) {// if (nums[i] === nums[i + 1]) {// res.push(nums[i], nums[i] + 1)// }// }// return res// }// 考虑重复的数字不相邻问题:判断当前项与下一项相同的同时,加上判断下下一项是否等于当前项+1的值(不存在当前值则判断前一项值是否相差1)// 如果相同,则重复丢失的数据不是相邻项;不相同则是// 不存在,判断当前值和前一项值是否相差1,如果是则是第一项减一的值为丢失数据的值,如果不是,这是当前项减一为丢失数据的值// 穷举所有情况的方式,失败❌,太多情况需要考虑到了,而且数据量大的时候不好处理var findErrorNums = function (nums) {const res = []nums.sort((a, b) => a - b)console.log(nums)for (let i = 0; i < nums.length; i++) {if (nums[i] === nums[i + 1]) {if (i + 2 < nums.length) {if (nums[i] + 1 === nums[i + 2]) {if (i !== 0) {if (nums[i] - 1 === nums[i - 1]) {if (nums[i - 1] === 1) {res.push(nums[i], nums[nums.length - 1] + 1)} else {res.push(nums[i], nums[i - 1] - 1)}} else {res.push(nums[i], nums[i] - 1)}} else {res.push(nums[i], nums[i] - 1)}} else {res.push(nums[i], nums[i] + 1)}} else {if (i === 0 || nums[i] - 1 === nums[i - 1]) {if (nums[0] >= 2) {res.push(nums[i], nums[0] - 1)} else {res.push(nums[i], nums[i] + 1)}} else {res.push(nums[i], nums[i] - 1)}}}}return res}// 解法三:map数字标记法(map的集合元素唯一性)注意题目信息:1到n的整数集合,说明数组nums最大值是n,最小值是1,跟数组索引对应// 第一步:遍历数组所有元素值,对应key-value为数组索引值和是否重复的索引值,重复的索引值value更改为2,否则默认为1// 第二步:遍历数组,判断当前索引对应map的key值是不是等于2,说明是重复的数字位置,判断当前索引是否为空,为空则为丢失的位置数字var findErrorNums = function(nums) {const map = new Map()let res = []for (const value of nums) {if (map.has(value)) {map.set(value, map.get(value) + 1)} else {map.set(value, 1)}}for (let i = 1; i <= nums.length; i++) {if (map.get(i) === 2) res[0] = iif (!map.get(i)) res[1] = i}return res}// const case2 = findErrorNums(nums = [1, 2, 2, 4]) // [2,3]// const case2 = findErrorNums([2, 2]) // [2,1]// const case2 = findErrorNums([1, 1]) // [1, 2]// const case3 = findErrorNums([5, 5, 6]) // [5, 4]// const case3 = findErrorNums([2, 2, 3]) // [2, 1]// const case3 = findErrorNums([3, 2, 2]) // [2, 1]// const case3 = findErrorNums([1, 3, 3]) // [3, 2]// const case3 = findErrorNums([1, 2, 3, 3, 6, 5]) // [3, 4]// const case3 = findErrorNums([ 2, 3, 3, 4, 5, 6 ]) // [3, 1]// const case3 = findErrorNums([ 2, 3, 4, 4, 5 , 7 ]) // [4, 1]// const case3 = findErrorNums([ 1, 3, 3]) // [3, 2]// const case3 = findErrorNums([8, 7, 3, 5, 3, 6, 1, 4]) // [3, 2]// const case3 = findErrorNums([3,2,3,4,6,5]) // [3, 1]const case3 = findErrorNums([5,3,6,1,5,4,7,8]) // [5, 2]console.log(case3)
解题感受
一开始只会用传统穷举的方法解题,测试用例通过20题报错后发现这个解题思路不太正确就换了另一种解题思路,不过想了10分钟没有思路看别人的解法才想到的,看懂后加上自己的理解注释做了出来(详细看打卡链接注释内容)
真的要多注意审题,看完题目做了一会还是没有思路的时候,做好的方式再坚持一下,看看从题干中分析解题思路和寻找破解口
