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

LeetCode面试经典150题—01 合并有序数组_第1张图片

思路

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

    这是很容易想到的一种思路,用双指针思想分别遍历比较两个数组中数的大小,将较小的那个数依次放入新创建的数组中,最后将该数组拷贝到 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);

}

LeetCode面试经典150题—01 合并有序数组_第2张图片

问题:没有利用好 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--];
        }

    }

LeetCode面试经典150题—01 合并有序数组_第3张图片

  • 思路二:先合并再排序

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

    代码如下:

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

LeetCode面试经典150题—01 合并有序数组_第4张图片


数组拷贝方法拓展

  • System.arraycopy()

源码:

LeetCode面试经典150题—01 合并有序数组_第5张图片

参数:

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()

源码:

LeetCode面试经典150题—01 合并有序数组_第6张图片

从源码可以看出,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 方法详解


 

你可能感兴趣的:(LeetCode,leetcode,面试,java,算法)