【代码随想录】回溯专题1(Python)

1.组合

77.组合
递归+剪枝

class Solution:
    def combine(self, n: int, k: int) -> List[List[int]]:
        result = []
        path = []
        def backtracking(n:int, k:int, startint:int):
            if len(path)==k:
                result.append(path.copy())
                return
            for i in range(startint, n-(k-len(path))+1+1):
                path.append(i)
                backtracking(n,k,i+1)
                path.pop()
        backtracking(n, k, 1)
        return result

2.组合总和III

216.组合总和III
剪枝:for循环中范围值剪枝,sum大小剪枝

class Solution:
    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        result = []
        path = []
        def backtracking(k:int, n:int, startint:int, sum:int):
            if sum > n:
                return
            if len(path)==k:
                if sum==n:
                    result.append(path.copy())
                return
            for i in range(startint,11-(k-len(path))):
                path.append(i)
                sum += i
                backtracking(k, n, i+1, sum)
                path.pop()
                sum -= i
        backtracking(k, n, 1, 0)
        return result

3.电话号码的字母组合

17.电话号码的字母组合
回溯二叉树的宽度为每个数字对应字母的个数,深度为digits的长度。

class Solution:
    def __init__(self) -> None:
        self.path = ""
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits: return []
        result = []
        dic = ["", "", "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"]
        def backtracking(digits:str, startint:int):
            if len(self.path)==len(digits):
                result.append(self.path)
                return
            for i in range(len(dic[int(digits[startint])])):
                self.path += dic[int(digits[startint])][i]
                backtracking(digits,startint+1)
                self.path = self.path[:-1]
        backtracking(digits, 0)
        return result

4.组合总和

39.组合总和
终止条件增加:sum>target即return
剪枝:sum+i > target则结束循环
注:candidates要排序

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates = sorted(candidates)
        result = []
        path = []
        def backtracking(candidates: List[int], target: int, sum:int, startint:int):
            if sum > target: return
            elif sum == target:
                result.append(path.copy())
                return
            else:
                for i in range(startint,len(candidates)):
                    if sum+candidates[i]>target: return
                    path.append(candidates[i])
                    sum += candidates[i]
                    backtracking(candidates, target,sum,i)
                    sum -= candidates[i]
                    path.pop()
        backtracking(candidates, target, 0, 0)
        return result

5.组合总和II

40.组合总和II
剪枝:利用used数组,剪去横枝(与前一相同的枝不要),保留竖枝

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        result = []
        path = []
        used = [0]*len(candidates)
        def backtracking(candidates: List[int], target: int, sum:int, startint:int):
            if sum > target: return
            elif sum == target:
                result.append(path.copy())
                return
            for i in range(startint, len(candidates)):
                if sum+candidates[i]>target: return
                if i>0 and used[i-1]==0 and candidates[i-1]==candidates[i]: continue
                path.append(candidates[i])
                sum += candidates[i]
                used[i] = 1
                backtracking(candidates, target, sum, i+1)
                used[i] = 0
                sum -= candidates[i]
                path.pop()
        backtracking(sorted(candidates), target, 0, 0)
        return result

6.分割回文串

131.分割回文串
横向:目标串长度,i(startint+1:len(s)+1)
纵向:起始位置>=目标串长度
注:切片始末位置

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        if not s: return []
        result = []
        path = []
        def isPalindrome(s:str):
            for i in range(int(len(s)/2)):
                if s[i]!=s[len(s)-i-1]:
                    return False
            return True
        def backtracking(s:str, startint:int):
            if startint>=len(s):
                result.append(path.copy())
                return
            for i in range(startint+1,len(s)+1):
                t = s[startint:i]
                if isPalindrome(t):
                    path.append(t)
                    backtracking(s, i)
                    path.pop()
        backtracking(s,0)
        return result

6.复原IP地址

93.复原IP地址
横向:目标串长度(startint,len(s))超过3位数不合法
纵向:3(最后一段判断是否合法)
注:判断非法字符

class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        if len(s) > 12: return []
        result = []
        def isvalid(s:str, start:int, end:int):
            if start>=end: return False
            if s[start]=='0' and (end-start)>1: return False
            if not 0<=int(s[start:end])<=255: return False
            return True
        def backtracking(s:str, startint:int, path:str, flag:int):
            if flag == 3:
                if isvalid(s,startint,len(s)):
                    path += s[startint:]
                    result.append(path)
                return
            for i in range(startint,len(s)):
                if isvalid(s,startint,i+1):
                    t = t = s[startint:i+1]
                    path = path + t + "."
                    backtracking(s,i+1,path,flag+1)
                    path = path[:-len(t)-1]
                
        backtracking(s,0,"",0)
        return result

7.子集

78.子集
每一个节点都添加,而不是叶子节点添加

class Solution:
    def subsets(self, nums: List[int]) -> List[List[int]]:
        result = []
        path = []
        def backtracking(nums: List[int], startint:int):
            result.append(path.copy())
            if startint==len(nums):
                return
            for i in range(startint, len(nums)):
                path.append(nums[i])
                backtracking(nums,i+1)
                path.pop()
        backtracking(nums,0)
        return result
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值