🚩传送门:力扣题目
牛客题目

题目

给你一个含 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图1 个整数的数组 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图2 ,其中 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图3 在区间 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图4 内。请你找出所有在 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图5 范围内但没有出现在 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图6 中的数字,并以数组的形式返回结果。

示例 1:

输入:nums = [4,3,2,7,8,2,3,1] 输出:[5,6]

示例 2:

输入:nums = [1,1] 输出:[2]

解题思路:原地修改

用一个哈希表记录数组 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图7 中的数字,再利用哈希表检查 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图8 中的每一个数是否出现,从而找到缺失的数。

由于数字范围均在 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图9 中,我们也可以用一个长度为 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图10 的数组来代替哈希表。这一空间复杂度是 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图11 。我们的目标是优化空间复杂度到 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图12

备注:注意到 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图13 的长度恰好也为 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图14,能否让 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图15 充当哈希表呢 ?

由于 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图16 的数字范围均在[NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图17中,我们可以利用这一范围之外的数字,来表达「是否存在」的含义。

具体来说,遍历 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图18 ,每遇到一个数 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图19,就让 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图20 增加 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图21。由于 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图22 中所有数均在 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图23 中,增加以后,这些数必然大于 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图24 。最后我们遍历 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图25 ,若 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图26 未大于 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图27,就说明没有遇到过数 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图28。这样我们就找到了缺失的数字。

注意,当我们遍历到某个位置时,其中的数可能已经被增加过,故需要对 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图29 取模来还原出它本来的值。

复杂度分析

时间复杂度:[NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图30,其中 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图31 是数组 [NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图32 的长度。

空间复杂度:[NC]256. 数组里面没有出现过的数字/找到所有数组中消失的数字 - 图33

官方代码

  1. class Solution {
  2. public List<Integer> findDisappearedNumbers(int[] nums) {
  3. int n = nums.length;
  4. //0.遍历标记
  5. for (int num : nums) {
  6. //1.取余取真值
  7. int x = (num - 1) % n;
  8. //2.利用下标+n标记
  9. nums[x] += n;
  10. }
  11. List<Integer> ret = new ArrayList<Integer>();
  12. for (int i = 0; i < n; i++) {
  13. if (nums[i] <= n) {
  14. ret.add(i + 1);
  15. }
  16. }
  17. return ret;
  18. }
  19. }