类别:数组 统计数组中的元素
题目:
法一:借助flag数组
想法:
初始化
flag数组存出现的数
resultList存结果(消失的数)
遍历原数组
将出现的对应存到flag中
遍历flag数组,若为0(消失的数),则加入i+1到列表resultList中
代码:
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
int[] flag=new int[nums.length];
int i=0;
while(i<nums.length){
flag[nums[i]-1]=nums[i];
i++;
}
ArrayList<Integer> resultList = new ArrayList<Integer>();
i=0;
while(i<nums.length){
if(flag[i]==0){
resultList.add(i+1);
}
i++;
}
return resultList;
}
}
法二:双循环变量
想法:
先对原数组进行排序
初始化
i、j两个循环变量,i负责遍历,j表示元素遍历
resultList存结果(消失的数)
遍历原数组
若nums[i]==j(即未消失),则若该元素未重复/为最后一个数字,则j++
否则 存下此消失的数
j++(查看下一个元素是否消失),i--重新判断这一位(可能连着消失好几个)
遍历完成后 不要忘记 j~nums.length这些数(如有)也是消失的噢!
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
int i=0;
int j=1;
Arrays.sort(nums);
ArrayList<Integer> resultList = new ArrayList<Integer>();
while(i<nums.length){
if(j==nums[i]){
if(i<nums.length-1 && nums[i]!=nums[i+1])
j++;
if(i==nums.length-1)
j++;
}else{
resultList.add(j);
j++;
i--;
}
i++;
}
while(j<=nums.length){
resultList.add(j);
j++;
}
return resultList;
}
}
本以为少开一个flag可以内存消耗少点 哈哈哈哈哈....
法三:原地修改(官方题解)
由于nums 的数字范围均在 [1,n]中,我们可以利用这一范围之外的数字,来表达「是否存在」
具体来说,遍历nums,每遇到一个数 x,就让 nums[x−1] 增加 n。由于nums 中所有数均在 [1,n]中,增加以后,这些数必然大于 n。最后我们遍历nums,若nums[i] 未大于 n,就说明没有遇到过数 i+1。这样我们就找到了缺失的数字。
class Solution {
public List<Integer> findDisappearedNumbers(int[] nums) {
int n = nums.length;
for (int num : nums) {
int x = (num - 1) % n;
nums[x] += n;
}
List<Integer> ret = new ArrayList<Integer>();
for (int i = 0; i < n; i++) {
if (nums[i] <= n) {
ret.add(i + 1);
}
}
return ret;
}
}
和法一没差多少