題目來源:https://leetcode-cn.com/problems/permutations/python
給定一個 沒有重複 數字的序列,返回其全部可能的全排列。數組
示例:bash
輸入: [1,2,3] 輸出: [ [1,2,3], [1,3,2], [2,1,3], [2,3,1], [3,1,2], [3,2,1] ]
思路:深度優化搜索微信
先看題目,以所給數組 [1, 2, 3] 的全排列爲例:app
從上面的狀況,能夠看出。枚舉每一個每一位可能出現的狀況,已選擇的數字在下面的選擇則不能出現。按照這個作法,全部的狀況將可以羅列出來。這裏其實就是執行一次深度優先搜索,從根節點到葉子節點造成的路徑就是一個全排列。優化
按照這種思路,沿用上面的例子,從空列表 []
開始,以 1 開始爲例。如今肯定以 1 開始,則列表爲 [1]
,如今選擇 [2]
和 [3]
之中的一個,先選 2
,最後剩下的只有數字 3
,因此造成全排列 [1, 2, 3]
。spa
已知還有一種狀況,也就是 [1, 3, 2]
,那麼如何實現從 [1, 2, 3]
到 [1, 3, 2]
的變化。深度優先搜索是如何實現的?實際上是從 [1, 2, 3]
回到 [1, 2]
的狀況,撤銷數字 3,由於當前層只能選擇 3,因此再撤銷 2 的選擇,這樣後面的程序則能在選擇 3 的時候後續也能選擇 2。code
class Solution: def permute(self, nums: List[int]) -> List[List[int]]: def _dfs(nums, depth, pmt, be_selected, length, ans): # 表示深度優化搜索的深度等於數組長度時,這個時候表示全排列已經生成 # 也就是符合狀況的選擇已經選擇完畢 # 將這個全排列的狀況添加到列表中 # 這裏須要注意,pmt 在參數傳遞是引用傳遞,拷貝一份添加到結果中 if depth == length: ans.append(pmt[:]) return # 開始遍歷 for i in range(length): # be_selected,表示原數組中的元素的狀態,是否被選擇,是爲 True,否爲 False if not be_selected[i]: # 當元素被選擇時,改變狀態 be_selected[i] = True # 將元素添加到 pmt 中,以構成後續 pmt.append(nums[i]) # 向下一層進行遍歷 _dfs(nums, depth + 1, pmt, be_selected, length, ans) # 遍歷結束時,進行回溯,這個時候狀態要進行重置 # 如上面說的 `[1, 2, 3]` 到 `[1, 3, 2]` 中變化,要撤銷 3,再撤銷 2,從新選擇 # 狀態改變 be_selected[i] = False # 撤銷 pmt.pop() length = len(nums) if length == 0: return [] be_selected = [False] * length ans = [] _dfs(nums, 0, [], be_selected, length, ans) return ans
以上就是使用深度優化搜索的思想,解決《46. 全排列》的問題的主要內容,主要須要注意的是狀態重置。
歡迎關注微信公衆號《書所集錄》