代码随想录Day22|回溯1|组合+分割

组合

77.组合

  • 回溯典型题目,注意细节和剪枝优化
class Solution:
    def backtrace(self,path,inum):
        if len(path) == self.k:
            self.ans.append(path[:])
            return
        ## 完全回溯
        # for i in range(inum,self.n+1):
        ## 剪枝
        for i in range(inum,self.n-(self.k-N)+1+1):
            self.backtrace(path+[i],i+1)
    def combine(self, n: int, k: int) -> List[List[int]]:
        self.ans = []
        self.k = k
        self.n = n
        self.backtrace([],1)
        return self.ans

216.组合总和Ⅲ

  • 跟上题差不多,剪枝多一个总和大于就返回
class Solution:
    def backtrace(self,path,num):
        if len(path)==self.k and sum(path)==self.n:
            self.ans.append(path[:])
            return 
        if sum(path)>=self.n:
            return
        for i in range(num,9-(self.k-len(path))+1+1):
            self.backtrace(path+[i],i+1)

    def combinationSum3(self, k: int, n: int) -> List[List[int]]:
        self.k = k
        self.n = n
        self.ans =[]
        self.backtrace([],1)
        return self.ans

17.电话号码的字母组合

  • 回溯思路: for 循环横向遍历,递归纵向遍历
class Solution:
    def backtrace(self,path,digits):
        if not digits:
            self.ans.append(path)
            return
        
        for i in self.dicts[digits[0]]:
            self.backtrace(path+i,digits[1:])

    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        self.dicts = {'2':'abc','3':'def','4':'ghi','5':'jkl','6':'mno','7':'pqrs','8':'tuv','9':'wxyz'}
        self.ans = []
        self.backtrace('',digits)
        return  self.ans

39.组合总和

  • 题目重点:允许重复选取数字但是数组不能重复,根据“回溯二叉树”可以写出解答
class Solution:
    def backtrace(self,path,candidates):
        if sum(path)==self.target:
            self.ans.append(path)
        if sum(path)>self.target:
            return
        for i,k in enumerate(candidates):
        ## 最开始写的时候没有减数组,导致答案数组有重复
        #   self.backtrace(path+[k],candidates)
            self.backtrace(path+[k],candidates[i:])
            
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.target = target
        self.ans = []
        self.backtrace([],candidates)
        return self.ans

40.组合总和Ⅱ

  • 牢记for 循环横向遍历,递归纵向遍历
  • 这里提供的数组有相同数字,答案数组不包括重复数组的话,横向遍历要去除相同数即可
class Solution:
    def backtrace(self,path,candidates,target,total):
        if total==target:
            self.ans.append(path)
        elif total>target:
            return 
        for i,k in enumerate(candidates):
            if i>0 and candidates[i]==candidates[i-1]:
                continue
            total += k
            self.backtrace(path+[k],candidates[i+1:],target,total)
            total -= k

    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        self.ans = []
        self.backtrace([],candidates,target,0)
        return list(self.ans)

分割

131.分割回文串

  • 将切割问题看作是组合问题
  • 注意逻辑细节
class Solution:
    def isTrue(self,s):
        left,right = 0,len(s)-1
        while(left<right):
            if s[left]!=s[right]:
                return False
            left += 1
            right -= 1
        return True
    
    def backtrace(self,path,s,ans):
        if not s:
            ans.append(path)
        for i in range(1,len(s)+1):
            temp = s[:i]
            if self.isTrue(temp) is False:
                continue
            self.backtrace(path+[temp],s[i:],ans)

    def partition(self, s: str) -> List[List[str]]:
        ans = []
        self.backtrace([],s,ans)
        return ans 

93.复原IP地址

  • 写是写出来了,但是运算时间和占用内存不够优,不懂怎么优化
class Solution:
    def restoreIpAddresses(self, s: str) -> List[str]:
        def backtrace(path,s,ans,k):
            if not s and k==4:
                ans.append(path[:-1])
            if k>4:
                return            
            for i in range(1,len(s)+1):
                if len(s[:i])>3 or (len(s[:i])>1 and s[:i][0]=='0') or int(s[:i])>255:
                    break
                backtrace(path+s[:i]+'.',s[i:],ans,k+1)
        ans = []
        backtrace('',s,ans,0)
        return a
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值