首页 > 技术文章 > 合并两个有序数组

hbhdhd 2020-10-06 10:54 原文

题目:88. 合并两个有序数组

方法一:

直接暴力将两个数组合并,然后再排序。

class Solution {
  public void merge(int[] nums1, int m, int[] nums2, int n) {
    System.arraycopy(nums2, 0, nums1, m, n);
    Arrays.sort(nums1);
  }
}
//arraycopy方法:五个参数分别为原数组及起始位置(要复制的)、目标数组及起始位置(要复制的),长度。

时间复杂度:O((n+m)log(n+m));

空间复杂度:O(1)。

方法二:双指针/从前往后

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int[] ans = new int[m + n];//也可以先复制nums1数组,以它为总数组,这样空间复杂度为O(m)
    int p1 = 0, p2 = 0;
    int p = 0;
    while (p1 < m && p2 < n) {
        ans[p++] = nums1[p1] < nums2[p2] ? nums1[p1++] : nums2[p2++];
    }
    if (p1 < m)
        System.arraycopy(nums1, p1, ans, p, m + n - p);
    if (p2 < n)
        System.arraycopy(nums2, p2, ans, p, m + n - p);
    System.arraycopy(ans, 0, nums1, 0, m + n);
}

时间复杂度:O(n+m)

空间复杂度:O(m+n)

方法三:双指针/从后往前

方法二因为从头改变nums1的值,需要用其他数组先储存nums1的值。我们可以从尾部开始修改nums1的值,因为根据题意,nums1预先留有足够的空间给nums2,也就是说他后面有一大部分是空的,我们根据两数组先填满这部分就不需用额外的空间了。

public void merge(int[] nums1, int m, int[] nums2, int n) {
    int p1 = m - 1, p2 = n - 1;
    int p = m + n;
    while (p1 >= 0 && p2 >= 0) {
        nums1[p--] = nums1[p1] > nums2[p2] ? nums1[p1--] : nums2[p2--];
    }
    System.arraycopy(nums2, 0, nums1, 0, p2 + 1);//这里:因为如果nums1还剩有元素的话,那么他们本身就位于nums1的头部,不需要重新复制,如果nums2还有元素,说明这些元素比nums1最小的元素还小,那么只需要从头开始复制剩下元素,排到nums1最前面即可。
}

 

推荐阅读