每日一道 LeetCode (19):合併兩個有序陣列

極客挖掘機發表於2020-08-16

每天 3 分鐘,走上演算法的逆襲之路。

前文合集

每日一道 LeetCode 前文合集

程式碼倉庫

GitHub: https://github.com/meteor1993/LeetCode

Gitee: https://gitee.com/inwsy/LeetCode

題目:合併兩個有序陣列

題目來源:https://leetcode-cn.com/problems/merge-sorted-array/

給你兩個有序整數陣列 nums1 和 nums2,請你將 nums2 合併到 nums1 中,使 nums1 成為一個有序陣列。

說明:

初始化 nums1 和 nums2 的元素數量分別為 m 和 n 。

你可以假設 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]

解題方案

這道題單純的從排序上來講並不是難題,畢竟題目中已經給出來兩個有序的陣列了,最簡單的迴圈一下長陣列,然後挨個比較下兩個陣列元素的大小,放到一個新陣列裡面就完事兒了。

這道題的難點在於,我們需要在 nums1 陣列中,完成兩個陣列的排序,這個就稍微有點坑了,這相當於要把 nums2 合併到 nums1 當中,還得要有序的合併進去。

這個彎有點難繞的,題目中雖然說最終的結果要在 nums1 當中,但是並沒有說不允許我們建立第三個陣列啊,我可以建立一個新的陣列,把 nums1 copy 到新的陣列中,然後再在 nums1 當中完成排序,這不也行麼。

接下來就是程式碼時間,很簡單,定義了兩個指標,一個是 copy_nums1 的指標,還有一個是 nums2 的指標,通過移動這兩個指標,來完成整個排序工作。

// 從前往後
public void merge(int[] nums1, int m, int[] nums2, int n) {
    int[] copy_nums1 = new int[m];
    System.arraycopy(nums1, 0, copy_nums1, 0, m);

    // copy_nums1 的指標
    int n1 = 0;
    // nums2 的指標
    int n2 = 0;
    // nums1 的指標
    int n0 = 0;

    while ((n1 < m) && (n2 < n)) {
        nums1[n0++] = copy_nums1[n1] < nums2[n2] ? copy_nums1[n1++] : nums2[n2++];
    }

    if (n1 < m) {
        System.arraycopy(copy_nums1, n1, nums1, n1 + n2, m + n - n1 - n2);
    }
    if (n2 < n) {
        System.arraycopy(nums2, n2, nums1, n1 + n2, m + n - n1 - n2);
    }
}

上面這種方案雖說能解決問題,但是有一點不大好,就是新建了一個陣列,多佔用了一個陣列的空間,既然題上說 nums1 的長度足夠上,我們從小到大排序不好排,那麼如果是從大到小呢?

思路基本上還是一個思路,定義兩個指標,然後倒序的將元素裝到 nums1 裡面。

// 從後往前
public void merge_1(int[] nums1, int m, int[] nums2, int n) {
    // nums1 有資料的尾部指標
    int n1 = m - 1;
    // nums2 的尾部指標
    int n2 = n - 1;
    // nums1 最終的尾部指標
    int n0 = m + n - 1;

    while ((n1 >= 0) && (n2 >= 0)) {
        nums1[n0--] = nums1[n1] < nums2[n2] ? nums2[n2--] : nums1[n1--];
    }

    System.arraycopy(nums2, 0, nums1, 0, n2 + 1);
}

今天這兩道題都不難,基本上搞清楚了方案以後,就是寫寫程式碼練練手。

相關文章