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)
相关推荐
CS创新实验室14 小时前
算法、齿轮与硅基大脑:数值计算发展简史
人工智能·算法·数值计算
海石16 小时前
1563分的简单题,可能就简单在能被暴力AC
算法·leetcode
海石16 小时前
1400分的dp汗流浃背之【交替子数组计数】
算法·leetcode
奋发向前wcx16 小时前
P2590 树的统计 题目解析
数据结构·算法·深度优先
imbackneverdie17 小时前
AI4S不止于分子药物:以MedPeer为代表的科研基建打开产业新增量
大数据·人工智能·算法·aigc·科研·学术·ai 4s
额鹅恶饿呃18 小时前
C语言中的数据结构和变量
c语言·数据结构·算法
运行时记录19 小时前
prompt-optimizer skill
算法
万法若空20 小时前
【数据结构-哈希表】哈希表原理
数据结构·算法·散列表
退休倒计时20 小时前
【每日一题】LeetCode 437. 路径总和 III TypeScript
算法·leetcode·typescript
学逆向的20 小时前
汇编——内存
开发语言·汇编·算法·网络安全