题目如下:
1.首先对于这种数组消失数字问题我想到的是用hashset将数组中的元素放进hashset中,由于hashset是不允许有重复元素的,所以放完以后再遍历1-n(因为题目说了,a[i]的范围在1-n之间),所以遍历1-n的过程中判断遍历的那个数是否在hashset中,如果不再则说明该数就是消失的数字。这个方法虽然简单,但是不太符合题目要求,因为题目要求不使用额外空间(题目是不建议使用hashset)
2.不使用hashset,那我可以先将该数组排序哇,排完序再遍历1-n和排好序的数组对比,就很容易得出消失的数字,但是貌似有不太符合题目要求,题目要求时间复杂度为O(n),可是排序使用了快排,复杂度已经是O(nlogn)了。
3.所以只好看题解了,题解的方法可太厉害了,题解用的原地修改法,其实看他题解半天也没搞清楚啥是原地修改,然后又是肯代码。
代码如下:
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
List<Integer> list = new ArrayList<>();
if(nums.length<2)return list;
Arrays.sort(nums);
if(nums[0]>1){
for(int j=1;j<nums[0];j++)
list.add(j);
}
for(int i=1;i<nums.length;i++){
if(nums[i]-nums[i-1]>1){
for(int j=nums[i-1]+1;j<nums[i];j++)
list.add(j);
}
}
if(nums[nums.length-1]<nums.length){
for(int j=nums[nums.length-1]+1;j<=nums.length;j++)
list.add(j);
}
return list;
}
}
其实它原地修改的意思是:因为数组中的元素全部在1-n之间,所以对num[num[i]]的位置进行标记,如何标记呢?就是将num[num[i]]的位置加上num.length,当标记完成以后再遍历一趟数组,判断数组对应位置是否大于nums.length,如果大于,则该数不是消失的数,若小于则是消失的数字。