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],每一步的操作類似,用遞歸就可以完成。