解题过程

:::info 题目链接
集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
给定一个数组 nums 代表了集合 S 发生错误后的结果。
请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回。 :::

  1. /**
  2. * @link https://leetcode.cn/problems/set-mismatch/
  3. * @title 645. 错误的集合
  4. * @description 集合 s 包含从 1 到 n 的整数。不幸的是,因为数据错误,导致集合里面某一个数字复制了成了集合里面的另外一个数字的值,导致集合 丢失了一个数字 并且 有一个数字重复 。
  5. * 给定一个数组 nums 代表了集合 S 发生错误后的结果。
  6. * 请你找出重复出现的整数,再找到丢失的整数,将它们以数组的形式返回
  7. * @param {number[]} nums
  8. * @return {number[]}
  9. */
  10. // 解法一:
  11. // var findErrorNums = function (nums) {
  12. // nums.sort((a, b) => a - b)
  13. // console.log(nums)
  14. // for (let i = 0; i < nums.length; i++) {
  15. // if (nums[i] === nums[i + 1]) {
  16. // // const minNums = nums.find(i => i !== nums[i])
  17. // if (nums[i] === 1) {
  18. // return [nums[i], nums[i + 1]]
  19. // } else if (nums[i] === 2) {
  20. // return [nums[i], 1]
  21. // }
  22. // // return [nums[i], Math.max(1, nums[i] - 1, nums[i] + 1)]
  23. // }
  24. // }
  25. // }
  26. // 解法二:穷举所有遇到的情况判断处理,结果失败
  27. // 不考虑排序,直接遍历数组nums, 判断当前索引项跟下一个索引项是否相同
  28. // 相同则记录当前值和下一个被重复的值 + 1 就是丢失的值❌,因为重复的值不一定就是相邻的数字,比如[ 2, 3, 4, 4, 5 , 7 ],重复的数字是4,但丢失的数字缺不是5
  29. // 暂不考虑数组排序问题,默认有小到大排好序
  30. // var findErrorNums = function (nums) {
  31. // const res = []
  32. // for (let i = 0; i < nums.length; i++) {
  33. // if (nums[i] === nums[i + 1]) {
  34. // res.push(nums[i], nums[i] + 1)
  35. // }
  36. // }
  37. // return res
  38. // }
  39. // 考虑重复的数字不相邻问题:判断当前项与下一项相同的同时,加上判断下下一项是否等于当前项+1的值(不存在当前值则判断前一项值是否相差1)
  40. // 如果相同,则重复丢失的数据不是相邻项;不相同则是
  41. // 不存在,判断当前值和前一项值是否相差1,如果是则是第一项减一的值为丢失数据的值,如果不是,这是当前项减一为丢失数据的值
  42. // 穷举所有情况的方式,失败❌,太多情况需要考虑到了,而且数据量大的时候不好处理
  43. var findErrorNums = function (nums) {
  44. const res = []
  45. nums.sort((a, b) => a - b)
  46. console.log(nums)
  47. for (let i = 0; i < nums.length; i++) {
  48. if (nums[i] === nums[i + 1]) {
  49. if (i + 2 < nums.length) {
  50. if (nums[i] + 1 === nums[i + 2]) {
  51. if (i !== 0) {
  52. if (nums[i] - 1 === nums[i - 1]) {
  53. if (nums[i - 1] === 1) {
  54. res.push(nums[i], nums[nums.length - 1] + 1)
  55. } else {
  56. res.push(nums[i], nums[i - 1] - 1)
  57. }
  58. } else {
  59. res.push(nums[i], nums[i] - 1)
  60. }
  61. } else {
  62. res.push(nums[i], nums[i] - 1)
  63. }
  64. } else {
  65. res.push(nums[i], nums[i] + 1)
  66. }
  67. } else {
  68. if (i === 0 || nums[i] - 1 === nums[i - 1]) {
  69. if (nums[0] >= 2) {
  70. res.push(nums[i], nums[0] - 1)
  71. } else {
  72. res.push(nums[i], nums[i] + 1)
  73. }
  74. } else {
  75. res.push(nums[i], nums[i] - 1)
  76. }
  77. }
  78. }
  79. }
  80. return res
  81. }
  82. // 解法三:map数字标记法(map的集合元素唯一性)注意题目信息:1到n的整数集合,说明数组nums最大值是n,最小值是1,跟数组索引对应
  83. // 第一步:遍历数组所有元素值,对应key-value为数组索引值和是否重复的索引值,重复的索引值value更改为2,否则默认为1
  84. // 第二步:遍历数组,判断当前索引对应map的key值是不是等于2,说明是重复的数字位置,判断当前索引是否为空,为空则为丢失的位置数字
  85. var findErrorNums = function(nums) {
  86. const map = new Map()
  87. let res = []
  88. for (const value of nums) {
  89. if (map.has(value)) {
  90. map.set(value, map.get(value) + 1)
  91. } else {
  92. map.set(value, 1)
  93. }
  94. }
  95. for (let i = 1; i <= nums.length; i++) {
  96. if (map.get(i) === 2) res[0] = i
  97. if (!map.get(i)) res[1] = i
  98. }
  99. return res
  100. }
  101. // const case2 = findErrorNums(nums = [1, 2, 2, 4]) // [2,3]
  102. // const case2 = findErrorNums([2, 2]) // [2,1]
  103. // const case2 = findErrorNums([1, 1]) // [1, 2]
  104. // const case3 = findErrorNums([5, 5, 6]) // [5, 4]
  105. // const case3 = findErrorNums([2, 2, 3]) // [2, 1]
  106. // const case3 = findErrorNums([3, 2, 2]) // [2, 1]
  107. // const case3 = findErrorNums([1, 3, 3]) // [3, 2]
  108. // const case3 = findErrorNums([1, 2, 3, 3, 6, 5]) // [3, 4]
  109. // const case3 = findErrorNums([ 2, 3, 3, 4, 5, 6 ]) // [3, 1]
  110. // const case3 = findErrorNums([ 2, 3, 4, 4, 5 , 7 ]) // [4, 1]
  111. // const case3 = findErrorNums([ 1, 3, 3]) // [3, 2]
  112. // const case3 = findErrorNums([8, 7, 3, 5, 3, 6, 1, 4]) // [3, 2]
  113. // const case3 = findErrorNums([3,2,3,4,6,5]) // [3, 1]
  114. const case3 = findErrorNums([5,3,6,1,5,4,7,8]) // [5, 2]
  115. console.log(case3)

解题感受

一开始只会用传统穷举的方法解题,测试用例通过20题报错后发现这个解题思路不太正确就换了另一种解题思路,不过想了10分钟没有思路看别人的解法才想到的,看懂后加上自己的理解注释做了出来(详细看打卡链接注释内容)

真的要多注意审题,看完题目做了一会还是没有思路的时候,做好的方式再坚持一下,看看从题干中分析解题思路和寻找破解口

优质解题参考