回溯-LeetCode46. 全排列

1、題目描述

https://leetcode-cn.com/problems/permutations/

給定一個 沒有重複 數字的序列,返回其所有可能的全排列。

輸入: [1,2,3]
輸出:
[
  [1,2,3],
  [1,3,2],
  [2,1,3],
  [2,3,1],
  [3,1,2],
  [3,2,1]
]

2、代碼詳解

進階題:回溯、剪枝-LeetCode47. 全排列 II(可重複數字) https://blog.csdn.net/IOT_victor/article/details/107073704

更簡潔的代碼(推薦!便於拓展,思路與下面的一樣)

class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        # nums 選擇列表,depth深度, path 路徑,used 標記數組!,res 結果
        def dfs(nums, size, depth, path, used, res):
            # 結束條件:nums 中的元素全都在 path 中出現
            if depth == size:
                res.append(path[:])  # 需要傳遞下path的拷貝,否則對path的修改會影響到結果
                return

            for i in range(size):
                # used[i]==False,表示未被用過
                if not used[i]:
                    # 做選擇
                    used[i] = True
                    path.append(nums[i])

                    # 進入下一層決策樹
                    dfs(nums, size, depth + 1, path, used, res)

                    # 撤銷選擇
                    used[i] = False
                    path.pop()

        size = len(nums)
        if len(nums) == 0:
            return []

        used = [False for _ in range(size)]
        res = []
        dfs(nums, size, 0, [], used, res)
        return res

nums = [1,2,3]
s = Solution()
print(s.permute(nums))

https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-python-dai-ma-java-dai-ma-by-liweiw/

另一種寫法

回溯法模板 https://leetcode-cn.com/problems/permutations/solution/hui-su-suan-fa-xiang-jie-by-labuladong-2/

回溯算法的框架如下,核心就是 for 循環裏面的遞歸,在遞歸調用之前「做選擇」在遞歸調用之後「撤銷選擇」

result = []
def backtrack(路徑, 選擇列表):
    if 滿足結束條件:
        result.add(路徑)
        return
    
    for 選擇 in 選擇列表:
        做選擇
        backtrack(路徑, 選擇列表)
        撤銷選擇
class Solution(object):
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        # nums 選擇列表, track 路徑
        def trackBack(nums, track):
            # 結束條件:nums 中的元素全都在 track 中出現
            if len(track) == len(nums):
                res.append(track[:])  # 需要傳遞下track的拷貝,否則對track的修改會影響到結果
                return
            for i in nums:
                # 排除不合法的選擇
                if i in track:
                    continue  # 結束當前循環進入下一循環
                # 做選擇
                track.append(i)
                # 進入下一層決策樹
                trackBack(nums, track)
                # 撤銷選擇
                track.pop()

        res = []
        track = []  # 路徑
        trackBack(nums, track)
        return res

nums = [1,2,3]
s = Solution()
print(s.permute(nums))

時間複雜度:O(n ∗ n!),其中 n 爲序列的長度

空間複雜度:O(n),其中 n 爲序列的長度。除答案數組以外,遞歸函數在遞歸過程中需要爲每一層遞歸函數分配棧空間,所以這裏需要額外的空間且該空間取決於遞歸的深度,這裏可知遞歸調用深度爲 O(n)

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