代码随想录算法训练营第23天 | 39.组合总和 40.组合总和Ⅱ 131.分割回文串

39.组合总和

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。
candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。
对于给定的输入,保证和为 target 的不同组合数少于 150 个。

解题

本题和我们之前讲过的77.组合、216.组合总和III有两点不同:
1.组合没有数量要求
2.元素可无限重复选取

报错:1.递归时不用i+1,因为可以重复取;2.回溯忘记处理sum了;
不想看剪枝。。
一个集合里找组合的都要startIndex的哈~

点击查看代码
class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        result=[]
        self.backtracking(candidates,target,0,0,[],result)
        return result
    
    def backtracking(self,candidates,target,sum,startIndex,path,result):
        if sum>target:
            return
        if sum==target:
            result.append(path[:])
            return
        for i in range(startIndex,len(candidates)):
            path.append(candidates[i])
            sum+=candidates[i]
            self.backtracking(candidates,target,sum,i,path,result)
            path.pop()
            sum-=candidates[i]

40.组合总和Ⅱ

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。
candidates 中的每个数字在每个组合中只能使用 一次 。
注意:解集不能包含重复的组合。

解题

这道题目和39.组合总和 (opens new window)如下区别:
1.本题candidates 中的每个数字在每个组合中只能使用一次。
2.本题数组candidates的元素是有重复的,而39.组合总和是无重复元素的数组candidates
去重:搜索过程中把同一树层使用过的元素去重,需要对数组排序!!

参数:增加一个bool型参数used
在candidates[i] == candidates[i - 1]相同的情况下:
1.used[i - 1] == true,说明同一树枝candidates[i - 1]使用过
2.used[i - 1] == false,说明同一树层candidates[i - 1]使用过,需要去重这部分!continue跳跳跳过!
if i > startIndex and candidates[i] == candidates[i - 1] and not used[i - 1]:continue
当以上三个条件都满足时,执行 continue 语句,跳过当前循环的剩余部分,直接进入下一次循环。

点击查看代码
class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
     used=[False]*len(candidates)
     result=[]
     candidates.sort()
     self.backtracking(candidates,target,0,0,used,[],result)
     return result

    def backtracking(self,candidates,target,sum,startIndex,used,path,result):
        if sum>target:
            return
        if sum==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
            sum+=candidates[i]
            path.append(candidates[i])
            used[i]=True
            self.backtracking(candidates,target,sum,i+1,used,path,result)
            used[i]=False
            path.pop()
            sum-=candidates[i]

131.分割回文串

给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是
回文串。返回 s 所有可能的分割方案。

解题

分割线就是startIndex,它也表示递归到哪一层,表示接下来处理的序列是从哪个开始
终止:分割线在最后,startIndex=len(s)
单层递归逻辑:多了个判断s[start_index: i + 1]是否是回文串
if s[start_index: i + 1] == s[start_index: i + 1][::-1]:

点击查看代码
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        result=[]
        self.backtracking(s,0,[],result)
        return result
        
    def backtracking(self,s,startIndex,path,result):
        if startIndex==len(s):
            result.append(path[:])
            return
        for i in range(startIndex,len(s)):
            if s[startIndex:i+1]==s[startIndex:i+1][::-1]:
                path.append(s[startIndex:i+1])
                self.backtracking(s,i+1,path,result)
                path.pop()
posted @ 2024-06-28 23:29  Y荷兰豆Y  阅读(3)  评论(0编辑  收藏  举报