合併兩個有序數組

題目來源:力扣(LeetCode)

題目詳情:

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

說明:

  初始化 nums1 和 nums2 的元素數量分別為 m 和 n 。
  你可以假設 nums1 有足夠的空間(空間大小大於或等於 m + n)來保存 nums2 中的元素。

示例:

  輸入:
    nums1 = [1,8,9,15,0,0,0,0,0], m = 4
    nums2 = [2,5,6,12,18], n = 5

  輸出: 

    [1,2,5,6,8,9,12,15,18]

 解法一:

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int[] result = new int[m+n];      // 創建一個大小為m+n的數組,確保裝的下所有排序的元素
        int i = 0;
        int j = 0;
        int k = 0;
        while(i < m && j < n){          // 從左往右,往result中裝數據
            if(nums1[i] <= nums2[j]){
                result[k++] = nums1[i++];
            }else{
                result[k++] = nums2[j++];
            }
        }
        while(i < m){            // 將nums1中剩餘元素加到result後面
            result[k++] = nums1[i++];
        }
        while(j < n){            // 將nums2中剩餘元素加到result後面
            result[k++] = nums2[j++];
        }
        for(int s = 0; s < result.length; s++){  // 將排好序的result拷貝給nums1
            nums1[s] = result[s];
        }
    }
}

  這種解法很簡單,也很容易理解。就是額外創建一個數組result數組的大小為m + n即所有排序元素的個數,用來往裏面從左到右、從小到大裝數據。創建三個指針i 指向數組nums1的第一個元素j 指向數組nums2的第一個元素k 指向數組result的第一個位置。

  比較nums1和nums2的指針所指向的當前元素的大小小的填入到result中 k 指向的位置,此時兩個指針都向前移動一位重複當前操作——填數據

  直到nums1和nums2其中一個數組遍歷完了,此時另一個未遍歷完的數組剩餘的數都大於result中的元素將這些數依次加到result後面。

  到現在我們得到了一個已經包含nums1和nums2中所有元素的排好序的數組result是還沒有結束,因為我們所要做的是合併兩個數組,也就是將nums2合併到nums1中最後nums1是一個合併好的、排好序的數組,我們當前的nums1還不是。所以,我們還要更新一下nums1將result中的元素拷貝到nums1中至此nums1才是題目要求的樣子

 解法二:

class Solution {
    public void merge(int[] nums1, int m, int[] nums2, int n) {
        int len1 = m - 1;
        int len2 = n - 1;
        int len = m + n - 1;
        while(len1 >= 0 && len2 >= 0) {
            nums1[len--] = nums1[len1] > nums2[len2] ? nums1[len1--] : nums2[len2--];
        }
        // 將nums2數組從下標0位置開始,拷貝到nums1數組中,從下標0位置開始,長度為len2+1
        System.arraycopy(nums2, 0, nums1, 0, len2 + 1);

    }
}

  這種方法相對巧妙一點,沒有額外的創建數組,減少了算法的空間複雜度。讓我們來看一看這種解法的思路是什麼吧。

  解法一的思路是從小到大填數,以此相反,這種解法是從大到小填數據,是在數組nums1上從後往前填數選擇大的填

  while循環中,當數組nums2中的元素都被填完後,nums1就排好序了當nums1中的元素被填完,而nums2中的元素還有一些時,語句 System.arraycopy(nums2, 0, nums1, 0, len2 + 1); 就發揮作用了,會將nums2中剩餘的元素加到nums1中使得nums1合併排序完成。

 

Tags: