【Leetcode】python - [88] Merge Sorted Array 個人解法筆記 | 內含 python while-else 用法說明 (updated: 2022/5/11)

題目出處

88. Merge Sorted Array

難度

Easy

題目分類

array, two-pointers

個人範例程式碼 - 2022/5/11

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.
        """
        m, n = m-1, n-1 # get last idx
        for idx in range(len(nums1)-1, -1, -1):
            if(m >= 0 and n >= 0):
                if nums1[m] < nums2[n]:
                    nums1[idx] = nums2[n] 
                    n -= 1
                else:
                    nums1[idx] = nums1[m] 
                    m -= 1
            elif m >= 0:
                nums1[idx] = nums1[m] 
                m -= 1   
            elif n >= 0:
                nums1[idx] = nums2[n] 
                n -= 1

最近在練習程式碼本身就可以自解釋的 Coding style,可以嘗試直接閱讀程式碼理解

算法說明

從尾巴開始往前填,注意一下順序即可

input handling

在 for 迴圈中一起處理

Boundary conditions

for 迴圈控制範圍

個人範例程式碼 - 2022/2/25

class Solution(object):
    def merge(self, nums1, m, nums2, n):
        """
        :type nums1: List[int]
        :type m: int
        :type nums2: List[int]
        :type n: int
        :rtype: None Do not return anything, modify nums1 in-place instead.
        """
        while (m > 0 and n > 0): 
            if(nums1[m-1] >= nums2[n-1]):
                nums1[m+n-1] = nums1[m-1] # put nums1[m] in to the last place of nums1
                m -= 1
            else:
                nums1[m+n-1] = nums2[n-1]
                n -= 1
        else:
            while n > 0: # m = 0
                nums1[m+n-1] = nums2[n-1]
                n -= 1
            # else m > 0, already in nums1

說明

這題我們可以先注意題目的敘述:
最需要思考的部分在於「題目希望最後的結果直接儲存在 nums1 裡面

雖然這樣的限制會使我們解題更加的「受到限制」,但反過來說,
其實這也是題目給我們「最大的提示」。

題目的 nums1 給的空間為 m+n,所以最後我們都會將所有的值擺入 nums1 中,
而因為我們可以無憂慮去更改的值為最後的 0,0,0… 部分
(因為這個值就算被改消失了,也不影響我們想計算的結果)

所以這邊可以推斷出一定要「從後面開始解」,「從最無痛的 0 開始取代」,

再來我們就可以來思考,什麼時候擺入 nums1的值? 什麼時候擺入 nums2 的值?
我們可以靠著題目所給的 m, n 來進行這樣的操作,透過值不斷擺入,
我們去移動 m, n 作為 index 的座標,即可順利完成此題目。

邊際情況處理

這題要注意的邊際情況為 m=0, n=0 的時候我們要怎麼處理,
而照題目的敘述,

  • n=0 基本上對我們來說沒差,因為 m 控制的 nums1 即代表我們要的答案
  • m=0 才是重點,如果還有剩餘的 n,都需要擺入 nums1 中,而位置索幸很好取得, 依然可以透過 m+n-1 算出
  • 注意 index 細節,才是這題要考細心的部分

    這題有很多 index 細節考驗著作答者的細心度,
    包含:

    • 迴圈的範圍僅限於 m, n > 0 時,其他需要進例外處理
    • m-1, n-1 才是當下座標
    • 要擺入的位置為 m+n-1
    • 處理到 n > 0 就應該停下,而非 n >= 0

    python while-else 用法說明

    一般來說,我們通常都只會使用到 while,
    但其實在 python 中,while 是可以搭配 else 使用的。

    邏輯如下:

    while(條件成立):
        # 成立時循環
    else: # 當不成立時,出現在這
        # 當條件不成立時,開始作這邊的事情
    

    這個寫法,可能很多人覺得好像有沒有 else 似乎不會有太大的影響?
    畢竟當 while 條件不成立後,後續的程式碼「本來就會執行

    沒有錯!!!! 但是這個小細節,卻可以讓我們的程式碼邏輯更漂亮!

    例如說當我們有無關 while 的相關內容,我們才應該擺在外面,
    但有時候是剛結束迴圈時有一些收尾的相關內容要處理,這時候用 else 的寫法就相當漂亮了!

    範例

    假設我們要把一個 mylist 「純手動」印成 [1,2,3] 的樣子,
    最後還要印出一個 finish!

    mylist = [1,2,3]
    idx = 0
    print('[', end = '')
    while(idx < len(mylist)):
        print(mylist[idx], ',')
        idx += 1
    else:
        print(']')
    print('finish!')
    

    這個例子應該就很好懂了,我們集中「把要處理 list 列印的動作」放在 while-else 裡面,
    最後比較無關的 finish! 放在 while-else 外面,
    這樣看起來程式碼邏輯有沒有比都放在外面更清楚了呢? (當然,見仁見智啦XDDD,我覺得有XD)

    特殊用法 - while-else 搭配 break 使用的情況

    這也是我近期解題才發現的,當 while - else 搭配 break 使用時,能發揮更好閱讀的效果!

    請讀者先想像一下,下面的程式碼會印出什麼呢?

    while(True):
        break
    else:
        print(1)
    print(2)
    

    答案不是 1 2 !!! 而是只有 2 !!!

    這樣我們就能夠更進階的使用這個功能了,

    • 「透過 while 迴圈條件結束的,寫在 else 裡面」
    • 「如果是透過 break 結束的,寫在最外面」

    使用方式可以看我下面這題的示範:

    https://wongwongnotes-github-io.pages.dev/python/leetcode-python-142/

    Reference