Leetcode46. 全排列

46. 全排列 問題描述
  給定一個 沒有重複 數字的序列,返回其所有可能的全排列。
在這裏插入圖片描述
解題思路: 很經典的題了,全排列問題,首先想到的就是回溯算法或者深度優先遍歷,看圖說話
在這裏插入圖片描述
按順序選擇一個數1,然後剩下的[2,3]同樣看一看成一個子問題,也進行同樣的操作。回溯算法編碼主要問題就是

1.路徑:也就是已經做出的選擇。
2.選擇列表:也就是你當前可以做的選擇。
3.結束條件:也就是到達決策樹底層,無法再做選擇的條件。

看到一位大佬寫的回溯的基本框架很受用:

result = []
def backtrack(路徑, 選擇列表):
    if 滿足結束條件:
        result.add(路徑)
        return
    
    for 選擇 in 選擇列表:
        做選擇
        backtrack(路徑, 選擇列表)
        撤銷選擇

  可以想象在一下平時做二叉樹的深度遍歷,因爲二叉樹就兩個選擇,所以每次都是travel(left.child)和travel(right.child),這個樹空間每一層的選擇是不固定的,所以需要用for循環來遍歷travel每個子節點,直到葉子節點就是滿足條件,其中有兩步非常重要就是做選擇和撤銷選擇,選擇就是對當前的選擇的路徑做一個邏輯處理,然後到達當前狀態,然後再進行走下一步,最後再撤回選擇,就是回到上一狀態,也就是回溯。

代碼如下

class Solution:
    def __init__(self):
        self.res = [] #用res保存結果
    def permute(self, nums: List[int]) -> List[List[int]]:
        self._permute(nums, 0)
        return self.res
    
    def _permute(self, nums,first): #傳入first表示的是當前到哪一步(狀態)
        if first==(len(nums)):
            self.res.append(nums[:]) #到達葉子節點就加入該路徑結果,nums[:]其實是對nums的一個copy,如果不拷貝,子列表每次都指向nums,改變nums就是改變了其子列表

        for idx in range(first, len(nums)):#對每個狀態進行了選擇
            nums[idx],nums[first] = nums[first], nums[idx]#做出選擇,改變狀態
            self._permute(nums, first+1) #探索下一步
            nums[idx],nums[first] = nums[first], nums[idx]##做出選擇,還原狀態

  其實還有個寫法類似於動態規劃,就是dp[1]到dp[2],dp[2]到dp[3],每一步的操作類似,用遞歸就可以完成。

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