[LeetCode] 88. 合并两个有序数组

Description

给你两个有序整数数组nums1nums2,请你将nums2合并到nums1中,使nums1成为一个有序数组。

说明:

初始化nums1nums2的元素数量分别为mn
你可以假设nums1有足够的空间(空间大小大于或等于 m + n)来保存nums2中的元素。

示例:

输入:
nums1 = [1,2,3,0,0,0], m = 3
nums2 = [2,5,6],       n = 3

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

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/merge-sorted-array
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。

Analyse

合并两个有序数组nums1和nums2,nums1的空间够放下nums2,不用开新的数组存结果

归并排序(Merge sort)

完整版的归并排序在这里不是最优解,因为数组的两部分已经有序了,可以直接双指针法开始merge,但这道题是个练习归并排序的好地方

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        // 先将 nums2 append 到 nums1
        // public static void arraycopy(Object src,int srcPos,Object dest,int destPos,int length)
        System.arraycopy(nums2, 0, nums1, nums1.length - nums2.length, nums2.length);
        int low = 0, high = nums1.length - 1;

        // merge sort
        mergeSort(nums1, low, high);
    }

    // 将数组拆分成两部分,直到有序
    private void mergeSort(int[] nums, int low, int high) {
        // base case
        if (low >= high) return;

        int mid = low + (high - low) / 2; // 不用(low + high) / 2 防止加法溢出

        mergeSort(nums, low, mid);
        mergeSort(nums, mid+1, high);

        merge(nums, low, mid, high);
    }

    // 合并两个有序数组(或数据的两个有序部分)
    private void merge(int [] nums, int low, int mid, int high) {
        // 双指针法
        int p = low, q = mid + 1;

        // 需要一个临时空间
        int[] tmpNums = new int[high - low + 1];
        int index = 0;
        while (p <= mid && q <= high) {
            if (nums[p] < nums[q]) {
                tmpNums[index++] = nums[p++];
            } else {
                tmpNums[index++] = nums[q++];
            }
        }

        while (p <= mid) {
            tmpNums[index++] = nums[p++];
        }

        while (q <= high) {
            tmpNums[index++] = nums[q++];
        }

        // 将排好序的值写回nums
        System.arraycopy(tmpNums, 0, nums, low, high - low + 1);
    }
}

将merge()改成下面这样就能击败100%了,时间复杂度O(n + m);空间复杂度O(n + m),空间复杂度还可以继续优化,只需要把nums1中的元素复制出来一份就行了O(m),再继续优化可以两个有序数组逆序比较,这样只需要O(1)

public void merge(int[] nums1, int m, int[] nums2, int n) {
    // 先将 nums2 append 到 nums1
    System.arraycopy(nums2, 0, nums1, m, n);

    // int low = 0, high = m - 1;

    // merge sort
    // mergeSort(nums1, low, high);
    merge(nums1, 0, m - 1, m + n - 1);
}
posted @ 2020-07-01 11:25  arcsinW  阅读(211)  评论(0编辑  收藏  举报