【算法】回溯

回溯

回溯和dfs关系密切

DFS基本思想:

  1. 本质是遍历决策树
  2. 关注路径选择列表结束条件
  3. 结合回溯:重点是撤销选择
res = []
def dfs(路径, 选择列表):
    if 满足结束条件:
        res.append(路径)
        return
    
    for 选择 in 选择列表:
        做选择
        dfs(路径, 选择列表)
        撤销选择

全排列

注意res.append(path[:]):是path的一个拷贝

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        def dfs(depth,size,path,seen):
            if depth==size:
                res.append(path[:])
            for i in range(size):
                if not seen[i]:
                    seen[i]=1
                    path.append(nums[i])
                    dfs(depth+1,size,path,seen)
                    seen[i]=0
                    path.pop()
        
        size=len(nums)
        seen=[0]*size
        res=[]
        dfs(0,size,[],seen)
        return res

注意,这里当if depth==size:时没有return,虽然下面的for函数即使运行,也会因为seen[i]=1,而不会对结果造成影响,但这是很不好的习惯

最好在dfs结束时,加上return

其实也可以用内置的permutations函数:

class Solution:
    def permute(self, nums: List[int]) -> List[List[int]]:
        res=[list(t)for t in permutations(nums)]
        return res

电话号码的字母组合

选择列表为:dic[str(digits[depth])]

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        dic={'2':['a','b','c'],'3':['d','e','f'],'4':['g','h','i'],'5':['j','k','l'],'6':['m','n','o'],'7':['p','q','r','s'],'8':['t','u','v'],'9':['w','x','y','z']}
        res=[]
        def dfs(depth,size,path,seen):
            if depth==size:
                res.append(''.join(path[:]))
                return
            for i in dic[str(digits[depth])]:
                seen[i]=1
                path.append(i)
                dfs(depth+1,size,path,seen)
                seen[i]=0
                path.pop()

        seen=defaultdict(int)            
        size=len(digits)
        if not size:return []
        dfs(0,size,[],seen)
        return res

括号生成

当左括号不多于n时,可以添加左括号

当左括号数量大于右括号时,可以添加右括号

class Solution:
    def generateParenthesis(self, n: int) -> List[str]:
        def dfs(depth,path,cnt):
            if depth==2*n:
                if cnt==0:res.append(''.join(path[:]))
                return 
            for x in ('(',')'):
                if x=='(' and cnt>=n:continue
                if x==')' and cnt<=0:continue
                path.append(x)
                if x=='(':
                    cnt+=1
                else:
                    cnt-=1
                dfs(depth+1,path,cnt)
                if x=='(':
                    cnt-=1
                else:
                    cnt+=1
                path.pop()

        
        res=[]
        dfs(0,[],0)
        return res

组合总和

since list is an unhashable type, we use Counter to remove duplication

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res=[]
        def dfs(sum,path):
            if sum==target:
                flag=True
                for r in res:
                    if len(r)==len(path):
                        if Counter(r)==Counter(path):
                            flag=False
                            break
                if flag:res.append(path[:])
                return
            if sum>target:return
            for c in candidates:
                path.append(c)
                dfs(sum+c,path)
                path.pop()
        dfs(0,[])
        return res
        
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

可可卷

不要看到我~~

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值