LeetCode No.面试题10.01 合并排序的数组

262 阅读2分钟

原题链接

给定两个排序后的数组 A 和 B,其中 A 的末端有足够的缓冲空间容纳 B。 编写一个方法,将 B 合并入 A 并排序。

初始化 A 和 B 的元素数量分别为 m 和 n。

示例:

输入:
A = [1,2,3,0,0,0], m = 3
B = [2,5,6], n = 3

输出: [1,2,2,3,5,6]

合并后排序

两个数组合到一起后进行排序。

  • 时间复杂度:O((m+n)log(m+n)) 可以理解为快排的时间复杂度
  • 空间复杂度:O(log(m+n)) 同样按照快排的复杂度来看

双指针

开辟一个新的空间,双指针从头开始,逐个比较数组的每个值,每次比较将较小的值放到新的数组中

  • 时间复杂度:O(m+n) 每个元素遍历一次
  • 空间复杂度:O(m+n) 开辟了新的数组空间存放排序后的值

逆向双指针

方法 2 中之所以要使用临时变量,是因为如果直接合并到数组 A 中,A 中的元素可能会在取出之前被覆盖。那么如何直接避免覆盖 A 中的元素呢?观察可知,A 的后半部分是空的,可以直接覆盖而不会影响结果。因此可以指针设置为从后向前遍历,每次取两者之中的较大者放进 A 的最后面

    public void merge(int[] A, int m, int[] B, int n) {
        int ia = m - 1;
        int ib = n - 1;
        int curr = m + n - 1;
        int v ;
        while(ia >= 0 || ib >= 0){
            if(ia == -1){
                v = B[ib--];
            }else if (ib == -1){
                v = A[ia--];
            }else if (A[ia] > B[ib]){
                v = A[ia--];
            }else{
                v = B[ib--];
            }
            A[curr--] = v;
        }
    }
  • 时间复杂度:O(m+n) 每个元素遍历一次
  • 空间复杂度:O(1) 没有使用额外空间