目录

三个月算法进阶--day15

深度优先遍历(回溯)

回到上一个节点时之前做了什么,之后就要做相应的逆操作,即“状态重置”

递归终止条件

状态:每一个结点表示了求解问题的不同阶段

python函数传列表再append是原地修改,append的项是列表要复制

记录

leetcode第46题全排列

时间复杂度:O(n X n!),递归树的深度为n

状态变量:

  1. 递归到第几层depth
  2. 已经选了哪些数path,这个列表只在末尾操作,所以是个栈
  3. 布尔数组used,不用遍历即可知道数是否被使用,以O(1)的时间复杂度完成判断
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        length = len(nums)
        depth = 0
        ans = []
        path = []
        used = [False] * length
        self.dfs(nums, length, depth, path, used, ans)
        return ans
    
    def dfs(self, nums, length, depth, path, used, ans):
        if depth == length:
            ans.append(path[:])  # 一次拷贝

        for i, t in enumerate(nums):
            if used[i] == True:
                continue
            else:
                path.append(t)
                used[i] = True
                self.dfs(nums, length, depth+1, path, used, ans)
                used[i] = False  # 回溯
                path.pop()

class Solution:
    def permute(self, nums):
        """
        :type nums: List[int]
        :rtype: List[List[int]]
        """
        def backtrack(first = 0):
            # 所有数都填完了
            if first == n:  
                res.append(nums[:])
            for i in range(first, n):
                # 动态维护数组
                nums[first], nums[i] = nums[i], nums[first]
                # 继续递归填下一个数
                backtrack(first + 1)
                # 撤销操作
                nums[first], nums[i] = nums[i], nums[first]
        
        n = len(nums)
        res = []
        backtrack()
        return res

感受

回溯算法体现了算法的精妙,不掌握难以解决特定问题。