代码随想录Day27|--回溯算法 39. 组合总和● 40.组合总和II● 131.分割回文串

39. 组合总和

class Solution:
    def backtracking(self, candidates, target, total, startIndex, path, result):
        if total > target:
            return
        if total == target:
            result.append(path[:])
            return

        for i in range(startIndex, len(candidates)):
            total += candidates[i]
            path.append(candidates[i])
            self.backtracking(candidates, target, total, i, path, result) 
            total -= candidates[i]
            path.pop()

    def combinationSum(self, candidates, target):
        result = []
        self.backtracking(candidates, target, 0, 0, [], result)
        return result

观察题目要求可知:1.组合中的元素可以无限制重复---因此,此题和以往的题目区别已经显现。我们在进行树结构的绘制的时候,所规定的index便不需要+1,因为元素可以重复。

2.绘制树结构,按照回溯流程进行解题,顺利写出代码即可。

40. 组合总和 II

class Solution:
    def backtracking(self,total,target,startIndex,candidates,used,path,result):
        if total > target:
            return 
        if total == target:
            result.append(path[:])
            return 
        for i in range(startIndex,len(candidates)):
            if i > startIndex and candidates[i] == candidates[i-1] and not used[i-1]:
                continue #此时进入树枝层

            total += candidates[i]
            path.append(candidates[i])
            used[i] = True
            self.backtracking(total,target,i + 1,candidates,used,path,result)
            used[i] = False
            total -= candidates[i]
            path.pop()

    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        used = [False] * len(candidates)
        candidates.sort()
        result = []
        self.backtracking(0,target,0,candidates,used,[],result)
        return result

        

在审题时,虽然注意到了题目的意思是在candidates中每个数字在集合中值出现一次,存在candidates中元素重复情况的存在,但是在解题时还是掉进了该陷阱中。归纳来讲就是---有重复元素没有重复组合。针对于该题目,我们首先需要的就是对于数组进行排序,使得在树结构的同一层中不存在重复元素, 在叶子结点可以有相同元素,这样可以防止重复组合的出现。

代码中:used使用布尔型进行判断,方便我们后续进行if判断和去重操作。

在全局变量中要事先分配used空间,然后再进行去重操作。

在该题中,比较抽象的就是在进行去重,如何去重以及去重什么?怎样针对性的进行去重?我将以绘制树结构来进行阐述。

candidates[i]==candidates[i-1]:说明前后有两个元素相同,此时会产生两种情况。 一种是在树层上get-1,另一种是在树枝上 get-1;此时我们需要想到,要保留树枝,去重树层,利用used来去重即可。used[i-1]==0说明在树层层面。

131. 分割回文串

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        result = []
        self.backtracking(s,0,[],result)
        return result

    def ispartition(self,s,startIndex,i):
        if s[startIndex:i+1] == s[startIndex:i+1][::-1]:
            return True
        else:
            return False

    def backtracking(self,s,startIndex,path,result):
        if startIndex == len(s):
            result.append(path[:])
            return
        for i in range(startIndex,len(s)):
            if self.ispartition(s,startIndex,i):
                path.append(s[startIndex:i+1])
                self.backtracking(s,i+1,path,result)
                path.pop()
        
        return result
    
    

回溯类型中的新题型---分割问题。

绘制树结构,发现答题思路和组合问题相似,借助图像帮忙理解该问题:

1.切割,切割后的字符串后期仍需用到;所切割的位置也要进行标记。

2.所保留的结果均在叶子结点。

 明确理解,在树结构中“|”就是我们在代码中所提到的startIndex。

依照回溯三部曲:终止条件:当分割线在字符串末尾终止;收集结果,一维数组加入二维数组中;所需遍历的元素集:所包含的字符串区间,用startIndex和i进行标记。处理节点:进行回文数的判断,需要再定义函数。递归和回溯操作和组合相同。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值