1. 程式人生 > 實用技巧 >【Leetcode刷題】漢諾塔

【Leetcode刷題】漢諾塔

https://leetcode-cn.com/problems/hanota-lcci/

先將最底層圓盤之上的圓盤看做一個整體。漢諾塔問題的本質是

  1. 將最底層圓盤之上的圓盤全部放到輔助柱上
  2. 將最底層圓盤放到目標柱上
  3. 遞迴地處理輔助柱上的圓盤

而第一步又可以變成一個目標柱為輔助柱的漢諾塔問題,即self.hanota(A[1:], C, B)

但是要注意這樣寫是錯誤的,因為切片操作產生了一個新的物件,導致不會直接修改到A

因此,需要一個索引記錄下A需要處理到哪個位置

class Solution(object):
    def hanota(self, A, B, C):
        """
        :type A: List[int]
        :type B: List[int]
        :type C: List[int]
        :rtype: None Do not return anything, modify C in-place instead.
        """
        # self.hanota(A[1:], C, B) 是錯誤的
        # 需要一個索引記錄下A需要處理到哪個位置
        def move(n, a, b, c):
            # 索引為0表示A中沒需要處理的元素了
            if n == 0:
                return
            # 1. 將最底層圓盤之上的圓盤全部放到輔助柱B上
            move(n-1, a, c, b)
            # 2. 將最底層圓盤放到目標柱上
            c.append(a.pop())
            # 3. 將輔助柱B上的圓盤移到目標柱
            move(n-1, b, a, c)

        # 因為索引為0表示A中沒有需要處理的元素
        # 因此n初始化為len(A),遍歷完A中所有元素後n剛好是0
        move(len(A), A, B, C)
  • 時間複雜度:O(2n)。

    推導:

    由於move函式的意義是將A中元素逐個移到C中,因此運算次數與n有關,設move函式的運算次數為T(n),則需要T(n-1)步將最底層圓盤之上的圓盤全部放到輔助柱B上,一步將最底層圓盤放到目標柱上,還需要T(n-1)步將輔助柱B上的圓盤移到目標柱。

    由此可得T(n) = 2T(n-1) + 1

    等式兩邊加一得T(n) + 1 = 2T(n-1) + 2

    因此可得T(n)是一個公比為2的等比數列,即T(n) = 2n

  • 空間複雜度:O(n)。遞迴深度是n