Given an array of integers where 1 ≤ a[i] ≤ n (n = size of array), some elements appear twice and others appear once.
Find all the elements of [1, n] inclusive that do not appear in this array.
Could you do it without extra space and in O(n) runtime? You may assume the returned list does not count as extra space.Example:
Input:
[4,3,2,7,8,2,3,1]
Output:
[5,6]
我自己做的相当笨的方法,遍历套遍历,非常笨。代码如下:
public class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
Arrays.sort(nums);
List<Integer> list = new ArrayList<Integer>();
int flag = 0;
for(int i = 1; i <= nums.length; i++) {
while(true) {
if(i == nums[flag]) {
if(flag < nums.length - 1) flag++;
break;
}
if(i < nums[flag] || i > nums[nums.length - 1]) {
list.add(i);
break;
}
flag++;
}
}
return list;
}
}
看到discuss里面的奇妙思路又跪了,简单解释下:
思路是这样的,数组的每个位置经历一次正负号的标记,标记后,如果该位置的值仍是正数,则说明其未被标记过,即该位置下标+1的对应数在数组中不曾出现。
标记的方法是遍历原数组中的每个值,每个值-1后,代表的是1到n排序后的下标,把对应下标上的数组值置为负数,证明其出现过。否则没有。
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> ret = new ArrayList<Integer>();
for(int i = 0; i < nums.length; i++) {
int val = Math.abs(nums[i]) - 1;
if(nums[val] > 0) {
nums[val] = -nums[val];
}
}
for(int i = 0; i < nums.length; i++) {
if(nums[i] > 0) {
ret.add(i+1);
}
}
return ret;
}