448. 找到所有数组中消失的数字给你一个含 n 个整数的数组 nums ,其中 nums[i] 在区间 [1, n] 内。请你找出所有在 [1, n] 范围内但没有出现在 nums 中的

实例化(instantiate)是指在面向对象的编程中,把用类创建对象的过程称为实例化。是将一个抽象的概念类,具体到该类实物的过程。实例化过程中一般由类名 对象名 = new 类名(参数1,参数2...参数n)构成

  类的实例是对象,要访问到类的成员,就必须通过类的实例(静态成员除外)。new在实例化中的作用是(此处暂不讨论继承中new隐藏基类的作用):创建对象和调用构造函数。以Car car=new Car()为例,此过程可分为两步:

   (1)首先是声明类型为Car的变量car,此时会在栈中为car变量分配一个内存,并使用NULL初始化(引用类型一般初始化为NULL)。即为:Car car=null

    ( 2 )  之后,new运算符真正派上用场,new先在堆中创建一个新的Car实例对象,调用了构造函数对该对象分配内存空间和对其初始化,之后将其引用赋予变量car,栈中的car变量指向新创建的实例对象。即为car=new Car();

    另外,new运算符还用于调用值类型的默认构造函数,如在结构类型中除了显式的赋值外,还可以使用new运算符,让其默认构造函数为数据成员赋值
 

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>();
     //泛型 目的使用 ret.add方法,数据类型为Integer
//ArrayList类是继承AbstractList抽象类和实现List接口的一个实现类,
//List是一个接口,而ArrayList是List接口的一个实现类, ArrayList 继承并实现了List。List有两个重要的实现类:ArrayList和LinkedList
// ret拥有List的属性和方法,不拥有ArrayList的
        for (int i = 0; i < n; i++) {
            if (nums[i] <= n) {
                ret.add(i + 1);
            }
        }
        return ret;
    }
}

List list = new ArrayList();这句创建了一个ArrayList的对象后把上溯到了List。此时它是一个List对象了,有些ArrayList有但是List没有的属性和方法,它就不能再用了。而ArrayList list=new ArrayList();创建一对象则保留了ArrayList的所有属性。

为什么一般都使用 List list = new ArrayList() ,而不用 ArrayList alist = new ArrayList()呢? 
问题就在于List有多个实现类,如 LinkedList或者Vector等等,现在你用的是ArrayList,也许哪一天你需要换成其它的实现类呢?,这时你只要改变这一行就行了:List list = new LinkedList(); 其它使用了list地方的代码根本不需要改动。假设你开始用 ArrayList alist = new ArrayList(), 这下你有的改了,特别是如果你使用了 ArrayList特有的方法和属性。 ,如果没有特别需求的话,最好使用List list = new LinkedList(); ,便于程序代码的重构. 这就是面向接口编程的好处。

到此///

方法1:利用:index = abs(num) - 1

但是题目中要求不让使用额外空间,那该怎么办呢?其实我们仔细观察一下记录数组,由于我们的数组元素是有范围的,范围在 1 ≤ a[i] ≤ n ( n = 数组大小 ) ,所以index = nums -1,那能不能只用原数组来做标记呢?可以的,上述的动画过程我是用颜色来做标记的,那在写程序的时候,我们可以用负号来做标记。主要是以下过程:

在原数组上进行一次遍历,在遍历的过程中,将遇到的元素所对应的index下的元素标记为负。最终那些index下的元素没有被标记的则说明,这个index对应的元素没有出现过。

解释几个词:

元素所对应的index:也就是index = num - 1,就是上面视频中记录数组中的index与num的对应关系。
index下的元素:就是上面视频中原数组index与num的对应关系。
index对应的元素:就是上面视频中记录数组中的index与num的对应关系。
用负号的原因

这样我们就可以把没有出现过的元素找出来了。可能有的小伙伴会说,把元素标记为负,又因为index = num - 1,那index不就变成负数了吗?这里取绝对值就可以了。每次遍历的时候,我们都取num的绝对值,index = abs(num) - 1,这样index就不会为负数了。这也是为什么要用负号的原因。

import java.util.ArrayList;
class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        List<Integer> result = new ArrayList<>();
        for(int i = 0; i<nums.length; i++){
            int num = Math.abs(nums[i])-1;
            nums[num] = -Math.abs(nums[num]);
        }
        for(int i = 0; i<nums.length; i++){
            if(nums[i] > 0) result.add(i+1); 
        }
        return result;
    }
}

力扣中视频

 这样4与5对应的值为5和6,说明原来数组中没有5和6

方法2:原地哈希,让索引对应初试应该对应的值,如果不对应则交换位置去对应。

两个if情况不需要交换,1:nums[index] == index + 1,即索引与值对应。2: if(nums[targetIndex] == nums[index])   原索引处已经对应,重复出现此值时候不需要再交换。

class Solution {
    public List<Integer> findDisappearedNumbers(int[] nums) {
        int len = nums.length;
        int index = 0;
        while(index < len){
            if(nums[index] == index + 1){
                index++;
            }else{
                int targetIndex = nums[index] - 1;
                if(nums[targetIndex] == nums[index]){
                    index++;
                    continue;
                }

                int temp = nums[targetIndex];
                nums[targetIndex] = nums[index];
                nums[index] = temp;
            }
        }

        List<Integer> res = new ArrayList<>();
        for(int i = 0; i < len; i++){
            if(nums[i] != i + 1)
                res.add(i + 1);
        }

        return res;
    }
}
链接:https://leetcode.cn/problems/find-all-numbers-disappeared-in-an-array/solution/java-yuan-di-ha-xi-si-lu-qing-xi-dai-ma-a12yd/

class Solution {
public:
  vector<int> findDisappearedNumbers(vector<int>&nums){
  int n=nums.size();
  for(auto& num:nums) //这里num为元素值,相当于遍历元素值。索引从头开始遍历
{
      int x=(num-1)%n;
      nums[x]+=n;
  }
   vector<int>ret;
   for(int i=0;i<n;i++) {
   if(nums[i]<=n) {
       ret.push_back(i+1);
     }
   }
  return ret;
  }
};

  • 13
    点赞
  • 19
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值