日新计划448. 找到所有数组中消失的数字

84 阅读1分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第19天,点击查看活动详情

一、题目描述:

448. 找到所有数组中消失的数字 - 力扣(LeetCode) (leetcode-cn.com)

给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。

示例 1:

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

示例 2:

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

提示:

  • n == nums.length
  • 1 <= n <= 10^5
  • 1 <= nums[i] <= n

进阶:你能在不使用额外空间且时间复杂度为 O(n) 的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。

二、思路分析:

之前做到过好几道类似的,都是可以用数组原地交换,映射到下标,就想这里用同样的方法行不行。

时空复杂度:O(n) O(1),但是提交看起来性能比较拉。只是为了复用之前的方法,第一次学了鸽笼法。第三次做还是不会。。所以这里只是确保下次遇见先能够做出来。

和前面的原地置换有点不同,这里会有重复的情况,比如两个1,如果是之前的原地置换,可能就卡死了(目标位置是1,当前也是1,不停的交换)。所以这里遇到target位置上的值一样的话,跳过就好。最后看哪个位置上的值和预期不符合。
思路还是比较简单的。

三、AC 代码:

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> res = new LinkedList<>();

        int n = nums.length;
        for(int i = 0; i < n; i++){// i -> i + 1
            if( i + 1 != nums[i]){
                int targetValue = nums[nums[i] - 1];
                if(targetValue == nums[i]) {
                    continue;
                }else{
                    nums[nums[i] - 1] = nums[i];
                    nums[i] = targetValue;
                    i--;
                }
            }
        }
        
        for(int i = 0; i < n; i++){
            if(nums[i] != i + 1){
                res.add(i + 1);// 这里是放i + 1(应该是哪个数), 而不是nums[i](现在是什么错误的数)
            }
        }

        return res;
    }
}

范文参考:

不需要额外空间,思路超级清晰,不点赞不给看~ - 找到所有数组中消失的数字 - 力扣(LeetCode)