leetcode 88. Merge Sorted Array 詳解 python3

一.問題描述

Given two sorted integer arrays nums1 and nums2, merge nums2 into nums1 as one sorted array.

Note:

  • The number of elements initialized in nums1 and nums2 are m and n respectively.
  • You may assume that nums1 has enough space (size that is greater or equal to m + n) to hold additional elements from nums2.

Example:

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

Output: [1,2,2,3,5,6]

二.解題思路

題目本身不難,但是要求in_place操作,

如果要求常數內存O(1),就稍微複雜一點。

介紹倆O(1)內存方法。

方法一:

考慮如果我們可以新開內存怎麼做?

我們新開一個數組(大小m+n),然後比較nums1第一個元素和nums2第一個元素誰小,誰更小就丟新開的數組裏面,然後繼續比較。

然而問題是不開新內存,注意題目說的nums1大小至少m+n,就會想是否可以這樣用?

但是nums1本身的元素已經佔在前面了,我們不能用,既然後面可以用,何不反其道而行?

對於上面假設不要求常數內存的例子,我們也可以比較nums1和nums2的最後一個元素,誰大就放在新開內存的最後面,慢慢迭代。

這樣子我們就可以利用本題nums1的特性,把數丟後面,也不會影響nums1本身的數。

有人可能會問是否會影響nums1本身的數?

思考什麼時候會影響nums1本身的數,假設nums1[i]被影響,影響是指nums1[i]這個數還沒被拿去比較,就已經被nums2某個數佔了,這說明nums2的大小至少得需要m+n-i+1(假設nums1[i]~nums[m+n-1]全被nums2的數佔了,雖然可能有部分被nums1本身值佔用,但是這部分不影響)。i最大是m,所以nums2的大小至少是m+n-m+1=n+1,然而nums2大小是n,因此不可能。

nums1[i]不可能會被nums1本身的數給影響。因爲nums1的數被移動末尾,並不影響nums1的值在nums1所佔的空間大小。

比如說nums1[10]被移動到nums1[100],雖然佔用了第100個位置,但是釋放了第10個位置。所以不會影響nums1的10之前數的數的處理。只有nums2的數加進nums1纔可能就影響nums2本身的值,因爲佔用了新的空間。

時間複雜度O(m+n-1),空間複雜度O(1)

方法二:

死方法,從左開始處理。

比較兩個數組的開頭,nums2的數小,就插進nums1裏面,然後將nums1之後的值全部右移1格。

小小的一個優化就是,不要出現一個nums2的值小於nums1的值就插入一次,判斷nums2連續的幾個值是不是都小於nums1的那個值,如果是的話就一次性插入nums2這幾個小於的值進nums1,畢竟插入操作很花時間。

詳細見代碼。

時間複雜度O(m*m),空間複雜度O(1);

更多leetcode算法題解法: 專欄 leetcode算法從零到結束  或者 leetcode 解題目錄 Python3 一步一步持續更新~

三.源碼

方法一

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        # 18
        total_len=m+n-1
        for i in range(total_len,-1,-1):
            if n<1:break
            if m<1:
                nums1[:n]=nums2[:n]
                break
            if nums1[m-1]>nums2[n-1]:
                nums1[i]=nums1[m-1]
                m-=1
            else:
                nums1[i]=nums2[n-1]
                n-=1
                
            

方法二:

class Solution:
    def merge(self, nums1: List[int], m: int, nums2: List[int], n: int) -> None:
        """
        Do not return anything, modify nums1 in-place instead.
        """
        # 18
        i,j=0,0
        len_nums1=len(nums1)
        while i<m:
            jstart=j
            while j<n:
                if nums2[j]<nums1[i]:j+=1
                else: break
            nums1[i+j-jstart:]=nums1[i:len_nums1-j+jstart]
            nums1[i:i+j-jstart]=nums2[jstart:j]
            m+=j-jstart
            i+=1
        nums1[m:m+n-j]=nums2[j:]

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章