将一个数组复制到另一个数组上(283. 移动零的思考)

一、复制数组

这是我做leetbook数组题的第一题时遇到的疑问,决定分两个情况考虑。

1、数组长度相等

假设nums和nums1是长度相等的两个数组。

1.1、用nums = nums1;

赋值前在这里插入图片描述


赋值后在这里插入图片描述
nums创建的时候在堆里面创建一块内存区域用来存储,nums指向这个内存地址A。
nums1创建后指向B。
现在令nums = nums1;则把num1的地址(或者说是引用)赋给了num,所以num也指向了B。
两个数组都指向堆中同一个内存区域,他们是共享里面的数据。

1.2、for循环

        for (int i = 0; i < nums1.length; i++){
            nums[i] = nums1[i];
        }

循环前:在这里插入图片描述


循环后:
在这里插入图片描述
成功改变nums数组内部内容,而没有改变其引用。

1.3、Arrays类

方法1:

在这里插入图片描述

nums = Arrays.copyOf(nums1,5);

方法2:

在这里插入图片描述

nums = Arrays.copyOfRange(nums1,0,5);

两种方法最后的索引都可以>数组的长度,然后后面的都会补上0。
两种方法都可以成功复制数组,而且我们发现原数组nums从524变成了526,说明这两种复制方法是创建了一个新数组,然后用等号左边的数组指向这个新数组。

在这里插入图片描述

1.4、System.arraycopy方法

在这里插入图片描述

语法:

System.arraycopy(originalArray, 0, targetArray, 0, originalArray.length);

参数分别是:(原数组,从原数组第几位开始,目标数组,从目标数组第几位开始,复制长度)
代码:

System.arraycopy(nums1,0,nums,0,5);

在这里插入图片描述
可以看出这个方法类似于我们的for循环,是直接改原来数组的内容,没有改引用。

2、数组长度不等

  1. 赋值法成功
  2. for循环要注意越界问题,会报java.lang.ArrayIndexOutOfBoundsException
  3. Arrays类法成功
  4. 注意越界问题,会报java.lang.ArrayIndexOutOfBoundsException

3、总结

最好用for循环。 因为如果下面那道题用其他的,会不通过,原因的话自己想一下就明白了。

二、LeetBook移动零

开始刷题了,但觉得从leetcode题库从0开始刷的话,不太适合我的学习方法。我喜欢模块化的学习,学完一个模块总结一个模块。
然后在力扣上找到了这个LeetBook,感觉挺好用的,适合我这种还没刷过几道题的萌新。
LeetBook

给定一个数组 nums,编写一个函数将所有 0 移动到数组的末尾,同时保持非零元素的相对顺序。

原题是在题库也可以找到:283. 移动零
我的代码:

class Solution {
    public void moveZeroes(int[] nums) {
        int[] nums1 = new int[nums.length];
        int j = 0;//用j记录前面0的个数
        for (int i = 0; i < nums.length; i++){
            if (nums[i] != 0 ){
                nums1[i-j] = nums[i];
            }else
                j++;
        }
               for (int i = 0; i < nums1.length; i++){
           nums[i] = nums1[i];
       }
}
}

在这里插入图片描述
照例,学习一下评论区大佬@Yanjun
的解法。

   //思路:设置一个index,表示非0数的个数,循环遍历数组,
    // 如果不是0,将非0值移动到第index位置,然后index + 1
    //遍历结束之后,index值表示为非0的个数,再次遍历,从index位置后的位置此时都应该为0
    public void moveZeroes(int[] nums) {
        if (nums == null || nums.length <= 1) {
            return;
        }
        int index = 0;
        for (int i = 0; i < nums.length; i++) {
            if (nums[i] != 0) {
                nums[index] = nums[i];
                index++;
            }
        }

        for (int i = index; i < nums.length; i++) {
            nums[i] = 0;
        }
    }

先对比思路,我是用一个通过比较非0索引和0索引的距离来对数组前几位赋值,显得麻烦、多此一举,Yanju的解法则不需要判断什么距离,只要遇到了非0元素就塞进去,然后index++就行了,最后才补0。
我需要学习的是他还做了输入验证if (nums == null || nums.length <= 1) { return; }
而且只用一个数组就解决了问题。
不过认真一想,确实不需要辅助数组,我做题比较少,习惯用辅助数组感觉安全点,但大可不必。

写完力扣的LeetBook<数组与字符串>学习笔记这篇博客后,再回看这道题,这其实就是27. 移除元素题的难度加强版,只是多了处理后面的0这个步骤。
快慢指针方法来做。这是我自己重新写的代码:

		public void moveZeroes(int[] nums) {
		if (nums == null)
            return;
        int j = 0;
        for (int i = 0; i < nums.length; i++)
            if (nums[i] != 0)   
            	nums[j++] = nums[i];  
        for (int i = j; i < nums.length; i++)   
            	nums[i] = 0;   
       	}

其实跟上面那个大佬写的代码差不多。

  • 3
    点赞
  • 16
    收藏
    觉得还不错? 一键收藏
  • 4
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值