一、题目要求
给你一个含 n
个整数的数组 nums
,其中 nums[i]
在区间 [1, n]
内。请你找出所有在 [1, n]
范围内但没有出现在 nums
中的数字,并以数组的形式返回结果。
二、初步解法
2.1 初步思想
使用一个长度为n的辅助数组,初始时元素都是0,遍历数组,给出现数字的位置赋值为1。遍历结束后,将辅助数组元素为0的下标打包成一个新数组返回。
2.2 代码实现
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
int[] temp = new int[nums.length+1];
//初始化辅助数组
for (int i = 0; i < nums.length; i++) {
temp[i] = 0;
}
for (int i = 0; i < nums.length; i++) {
temp[nums[i]] = 1;
}
List<Integer> list = new ArrayList<>();
//注意数组取值范围
for (int i = 1; i < nums.length+1; i++) {
if (temp[i] == 0) {
list.add(i);
}
}
return list;
}
}
2.3 运行结果
空间复杂度O(N),时间复杂度O(N)。
三、优化解法
3.1 算法思想
遍历数组,将遍历出的元素绝对值作为下标,将其对应的元素改为负数表示出现过。再遍历数组,未出现负数的位置表示元素未出现。
3.2 代码实现
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
for (int i = 0; i < nums.length; i++) {
//将元素绝对值下标存储的元素变为负值
nums[Math.abs(nums[Math.abs(i)])-1] = -Math.abs(Math.abs(nums[Math.abs(nums[Math.abs(i)])-1]));
}
List<Integer> list = new ArrayList<>();
//注意数组取值范围
for (int i = 0; i < nums.length; i++) {
if (nums[i] > 0) {
list.add(i+1);
}
}
return list;
}
}
3.3 运行结果
由于使用了Math库防止数字重复,因此效率有所降低。但防止了使用额外空间。