开启掘金成长之旅!这是我参与「掘金日新计划 · 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;
}
}