dfs思路回溯

思路:用path 记录,判断边界 什么时候退出dfs,然后for 放内容,path.append(), dfs(下一个) path.pop()恢复现场

python 复制代码
class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        phone = ["","","abc", "def","ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"]
        n=len(digits)
        if n==0:
            return []

        ans = []
        path = [''] * n  # 注意 path 长度一开始就是 n,不是空列表 最后连起来
        def dfs(i):
            if i==n:
                ans.append(''.join(path))
                return
            # 枚举每个可能
            for c in phone[int(digits[i])]:#
                path[i]=c 
                dfs(i+1)
        dfs(0)
        return ans
                
        

子集回溯形

子集

python 复制代码
class Solution:
    def subsets(self, nums):
        # res = [[]]
        # for i in nums:
        #     newSets = []
        #     for num in res:
        #         newSets.append([i] + num)
        #     res = res + newSets
        # return res
        # dfs
        res=[]
        n=len(nums)
        path=[]
        # 选或不选:讨论 nums[i] 是否加入 path
        def dfs(i:int )->None:
            if i==n:#自己构造完毕
                res.append(path[:])
                return
            # 不选
            dfs(i+1)# 考虑下一个数 nums[i+1] 选或不选
            # 选
            path.append(nums[i])
            dfs(i+1)# 考虑下一个数 nums[i+1] 选或不选
            path.pop()  # 恢复现场,撤销 path.append(nums[i])
        dfs(0)
        return res



python 复制代码
class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        # 选哪个数字
        ans=[]
        path=[]
        n=len(nums)
        def dfs(i):
            ans.append(path.copy())
            if i==n:
                return
            for j in range(i,n):
                path.append(nums[j])
                dfs(j+1)
                path.pop()
        dfs(0)
        return ans


枚举逗号在哪里

python 复制代码
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        # 分割子集看是不是会问
        ans=[]
        path=[]
        n=len(s)
        def dfs(i):
            if i==n:
                ans.append(path[:])
                return
            for j in range(i,n):# 枚举逗号在哪里
                t=s[i:j+1]
                if t==t[::-1]:
                    path.append(t)
                    dfs(j+1)
                    path.pop()
        dfs(0)
        return ans;


        
python 复制代码
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        # 选货不选 ,
        ans=[]
        path=[]
        n=len(s)
        #现在 s 未被分割的部分为 [start, n-1]
        # 当前位于下标 i,讨论是否在 i 和 i+1 之间切一刀
        def dfs(i,start):
            if i==n:
                ans.append(path.copy())
                return
            # 不分割
            if i<n-1:
                dfs(i+1,start)
            # 分割,那么得到子串 [start, i]
            t=s[start:i+1]
            if t==t[::-1]:
                path.append(t)
                # 现在 s 未被分割的部分为 [i+1, n-1]
                dfs(i+1,i+1)
                path.pop()
        dfs(0,0)
        return ans

        

组合型回溯

python 复制代码
class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        # ans=[]
        # path=[]
        # #枚举下一个数选哪个举选哪个:在 1 到 i 中选一个数,加到 path 末尾
        # def dfs(i):
        #     d=k-len(path)# 还要选 d 个数
        #     if d==0:#选完了
        #         ans.append(path.copy())
        #         return 

        #     # 枚举的数不能太小,否则后面没有数可以选 1,2 1,3
        #     for j in range(i,d-1,-1):
        #         path.append(j)
        #         dfs(j-1)
        #         path.pop()
        
        # dfs(n) # 从 n 开始倒着枚举
        # return ans

        # 选货不选
        ans=[]
        path=[]
         #选或不选:讨论 i 是否加入 path
        def dfs(i):
            d=k-len(path)
            if d==0:
                ans.append(path.copy())
                return
            # buxuan i
            if i>d:
                dfs(i-1)
            # xuan i
            path.append(i)
            dfs(i-1)
            path.pop()
        
        dfs(n)
        return ans



        
python 复制代码
class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        ans = []
        path = []

        def dfs(i: int, left_sum: int) -> None:
            d = k - len(path)  # 还要选 d 个数
            if left_sum < 0 or left_sum > (i * 2 - d + 1) * d // 2:  # 剪枝
                return
            if d == 0:  # 找到一个合法组合
                ans.append(path.copy())
                return
            # 枚举的数不能太小,否则后面没有数可以选
            for j in range(i, d - 1, -1):
                path.append(j)
                dfs(j - 1, left_sum - j)
                path.pop()  # 恢复现场

        dfs(9, n)  # 从 i=9 开始倒着枚举
        return ans



python 复制代码
class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        #对于括号字符串的任意前缀,右括号的个数不能超过左括号的个数
        # 选( 还是)

        ans=[]
        path=['']*(n*2)
        m=n*2
        def dfs(i,open): #i个括号, open是左括号个数
            if i==m:
                ans.append(''.join(path))
                return 
            # xuan (
            if open<n:
                path[i]='('
                dfs(i+1,open+1)
            if i-open<open: # ) 可以选
                path[i]=')'
                dfs(i+1,open)
        
        dfs(0,0)
        return ans

排列形回溯

python 复制代码
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # def dfs(x):
        #     if x == len(nums)-1:
        #         res.append(list(nums))
        #         return
        #     for i in range(x,len(nums)):
        #         nums[i],nums[x]=nums[x],nums[i] # 交换,将 nums[i] 固定在第 x 位
        #         dfs(x+1)
        #         nums[i],nums[x]=nums[x],nums[i] # 恢复交换
        
        # res=[]
        # dfs(0)
        # return res
        # 通用写法
        n=len(nums)
        path=[0]*n
        st=[False]*n #标记每个数字是否被用过
        ans=[]
        def dfs(x:int)->None:
            if x==n:
                ans.append(path[:])
                return 
            for i,on in enumerate(st):
                if not on:
                    # 当前i没被用过 放进去path里面标记用过
                    path[x]=nums[i]
                    st[i]=True
                    dfs(x+1)
                    st[i]=False
        
        dfs(0)
        return ans
python 复制代码
class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        # 选什么
        ans=[]
        n=len(nums)
        path=[0]*n
        vis=[False]*n
        # 枚举 path[i] 填 nums 的哪个数
        def dfs(i):
            if i==n:
                ans.append(path.copy())
                return
            for j in range(len(nums)):
                if not vis[j]:# 从没有选的数字中选一个
                    path[i]=nums[j]
                    vis[j]=True
                    dfs(i+1)
                    vis[j]=False# 恢复现场
                     # 注意 path 无需恢复现场,因为排列长度固定,直接覆盖就行
        dfs(0)
        return ans

            
        dfs(0)
相关推荐
_F_y2 小时前
仿RabbitMQ实现消息队列-客户端模块实现
c++·算法·rabbitmq
一只小小的芙厨2 小时前
KMP总结
算法
山峰哥2 小时前
SQL性能提升20倍的秘密:这些优化技巧让DBA都惊叹
开发语言·数据库·sql·编辑器·深度优先·宽度优先
生成论实验室2 小时前
《事件关系阴阳博弈动力学:识势应势之道》第十一篇:双脑协同——WOLM与大模型的共生智能
人工智能·算法·语言模型·架构·创业创新
上弦月-编程3 小时前
高效编程利器:转移表技术解析
c语言·开发语言·数据结构·算法·排序算法
薇茗3 小时前
【初阶数据结构】 左右逢源的分支诗律 二叉树2
c语言·数据结构·算法·二叉树
AZaLEan__3 小时前
算法考核题解
算法
MediaTea3 小时前
AI 术语通俗词典:ID3 算法
人工智能·算法
Morwit3 小时前
【力扣hot100】 221. 最大正方形
前端·算法·leetcode