LeetCode面试经典150题—01 合并有序数组

思路

  • 思路一:双指针 + 新建数组

    这是很容易想到的一种思路,用双指针思想分别遍历比较两个数组中数的大小,将较小的那个数依次放入新创建的数组中,最后将该数组拷贝到 nums1
    
    代码如下:

public static void merge(int[] nums1, int m, int[] nums2, int n) {
        
        int[] ans = new int[m + n];
        int p1 = 0, p2 = 0, p3 = 0;
        while (p1 < m && p2 < n) {
            if (nums1[p1] <= nums2[p2]) {
                ans[p3] = nums1[p1];
                p1++;
            } else {
                ans[p3] = nums2[p2];
                p2++;
            }
            p3++;
        }

        if (p1 == m) {
            for (int i = p2; i < n; i++) {
                ans[p3] = nums2[i];
                p3++;
            }
        } else {
            for (int i = p1; i < m; i++) {
                ans[p3] = nums1[i];
                p3++;
            }
        }

        System.arraycopy(ans, 0, nums1, 0, m + n);

}

问题:没有利用好 nums1 数组初始长度为 m + n 的特点,且新创建数组占用内存
优化:从后往前确认数组,直接在 nums1 上进行变化,注意 nums2 未完全插入的情况

代码如下:

public static void merge(int[] nums1, int m, int[] nums2, int n) {
        m--;
        n--;

        while (m >= 0 && n >= 0) {
            nums1[m + n + 1] = nums2[n] >= nums1[m] ? nums2[n--] : nums1[m--];
        }
        while (n >= 0) {
            nums1[m + n + 1] = nums2[n--];
        }

    }

  • 思路二:先合并再排序

    这种思路简单且代码量比较少,但是没有利用到题目中数组 非递减顺序 的条件

    代码如下:

public static void merge(int[] nums1, int m, int[] nums2, int n) {
        System.arraycopy(nums2, 0, nums1, m, n);
        Arrays.sort(nums1);
}


数组拷贝方法拓展

  • System.arraycopy()

源码:

参数:

src:源数组
srcPos:源数组要复制的起始位置
dest:目标数组
destPos:目标数组要复制的起始位置
length:要复制的数组长度

用法:

public static void main(String[] args) {
        int[] arr1 = new int[]{0, 1, 2, 5};
        int[] arr2 = new int[4];
        System.arraycopy(arr1, 0, arr2, 0, arr1.length);
        System.out.println(Arrays.toString(arr2));
}

//输出:[0, 1, 2, 5]
  • Arrays.copyOf()

源码:

从源码可以看出,Arrays.copyOf() 实际上就是调用的 System.arraycopy()

用法:

public static void main(String[] args) {
        int[] arr1 = new int[]{0, 1, 2, 5};
        int[] arr2 = Arrays.copyOf(arr1, arr1.length);
        System.out.println(Arrays.toString(arr2));
}

//输出:[0, 1, 2, 5]

  • clone()

用法:

public static void main(String[] args) {
        int[] arr1 = new int[]{0, 1, 2, 5};
        int[] arr2 = arr1.clone();
        System.out.println(Arrays.toString(arr2));
}

//输出:[0, 1, 2, 5]


注意在思路一中是不能用 clone() 来将新创建的数组拷贝给 nums1 的,这里的拷贝是给形参 nums1 重新赋值,改变了引用对象,并不会改变实参 nums1

这点与 Java 的值传递有关,可参考视频进行理解:
Java 到底是值传递还是引用传递

关于 clone() 的更多内容可参考文章:

Java 中 clone 方法详解


 

  • 5
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 3
    评论
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值