代码随想录算法训练营第27天

41 阅读2分钟

39.组合总和

class Solution:
    def __init__(self):
        self.track=[]
        self.res=[]
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.backtrack(target,0,candidates,0)
        return self.res
    def backtrack(self,target,Sum,candidates,start):
        if Sum==target:
            self.res.append(self.track.copy())
            return
        for i in range(start,len(candidates)):
            if candidates[i]+Sum > target:
                continue
            Sum+=candidates[i]
            self.track.append(candidates[i])
            self.backtrack(target,Sum,candidates,i)
            Sum-=candidates[i]
            self.track.pop()

40.组合总和Ⅱ

这道题相比39题,多了一个去重的逻辑,所以我们需要在上一道题解法的基础上进行修改。

  1. 对数组进行排序
  2. 添加新的剪枝逻辑
class Solution:
    def __init__(self):
        self.track=[]
        self.path=[]
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        self.backtrack(candidates,target,0,0)
        return self.path
    def backtrack(self,candidates,target,start,Sum):
        if Sum==target:
            self.path.append(self.track.copy())
            return
        for i in range(start,len(candidates)):
            if candidates[i]+Sum>target:
                break
            if i>start and candidates[i]==candidates[i-1]:
                continue
            Sum+=candidates[i]
            self.track.append(candidates[i])
            self.backtrack(candidates,target,i+1,Sum)
            Sum-=candidates[i]
            self.track.pop()

另外,如果是一个集合求组合的问题,是需要start的,如果是多个集合求组合,则不需要

131.分割回文串

这道题难度还是挺大的,关键在于两点:

  1. 怎么分割回文串
  2. 怎么判断是否是回文串
    先说第二个问题,相对简单一点,判断是否是回文串可以使用之前学过的双指针的思路,一个指针在头,一个指针在尾。
    对于切割问题,其实完全可以看作是组合问题:
  • 组合问题:选取一个a之后,在bcdef中再去选取第二个,选取b之后在cdef中再选取第三个.....。
  • 切割问题:切割一个a之后,在bcdef中再去切割第二段,切割b之后在cdef中再切割第三段.....。
    对于终止条件,通过画一个具体的数可以发现,当切割到字符串最后时,会找到一个切割方法。所以说组合和切割问题其实本质是一样的。
class Solution:
    def __init__(self):
        self.path=[]
        self.track=[]
    def partition(self, s: str) -> List[List[str]]:
        self.backtrack(0,s)
        return self.path
    def backtrack(self,startIndex,s):
        if startIndex>=len(s):
            self.path.append(self.track.copy())
        
        for i in range(startIndex,len(s)):
            if self.isPalindrome(startIndex,i,s):
                str_track=s[startIndex:i+1]
                self.track.append(str_track)
                self.backtrack(i+1,s)
                self.track.pop()

    
    def isPalindrome(self,start,end,sub_s):
        while start < end:
            if sub_s[start]!=sub_s[end]:
                return False
            start+=1
            end-=1
        return True