题目:
给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的数字,并以数组的形式返回结果。
进阶:你能在不使用额外空间且时间复杂度为
O(n)
的情况下解决这个问题吗? 你可以假定返回的数组不算在额外空间内。
示例一:
输入:nums = [4,3,2,7,8,2,3,1]
输出:[5,6]
示例二 :
输入:nums = [1,1]
输出:[2]
解法一:虽然完成了进阶任务,但是效率不佳,不过思路自我感觉还是不错的。
执行时间 18ms 内存消耗48.9 MB
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> list = new ArrayList<>();
//先给数组排个序
Arrays.sort(nums);
int j = 1;
for(int i = 0;i < nums.length;i++){
//nums的最小值为1,如果mums值与j相等,说明第一个数不缺失
if(nums[i] == j){
j++;
}else if(nums[i] > j){
//方法一的灵魂所在
//如果j值小于nums值,说明缺失等于当前j的值
list.add(j++);
//j + 1后再比较
i--;
}
}
//第一次循环结束后j的值等于nums中的最大值
//又因为nums取值在[1,n]区间,所以把j到n之间缺失的数补齐即可
for(int i = j;i <= nums.length; i++){
list.add(j++);
}
return list;
}
}
解法二: 依然完成了进阶任务,比方法一效率提升不少。
执行时间 5ms 内存消耗48.9 MB
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> list = new ArrayList<Integer>();
for (int i = 0;i < nums.length;i++) {
//遍历时数组中一些值被改为负数,所以要用绝对值计算下标
int n = Math.abs(nums[i]) - 1;
if(nums[n] > 0){
nums[n] = -nums[n];
}
}
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
list.add(i + 1);
}
}
return list;
}
}
思路:
遍历nums[],找到 |muns[i]| - 1 所对应的数组下标,让该下标对应的数组值取负。之后再遍历数组,找出数组值大于0的下标。
数组中存在大于0的数,意味着不存在X使 X - 1 = 数组值大于0的下标,所以缺失的数X = 数组值大于0的下标 + 1。
来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array