day27| 39+40+131

39. 组合总和

 

题目简述:

给你一个 无重复元素 的整数数组 candidates 和一个目标整数 target ,找出 candidates 中可以使数字和为目标数 target 的 所有 不同组合 ,并以列表形式返回。你可以按 任意顺序 返回这些组合。

candidates 中的 同一个 数字可以 无限制重复被选取 。如果至少一个数字的被选数量不同,则两种组合是不同的。 

对于给定的输入,保证和为 target 的不同组合数少于 150 个。

 

思路:

回溯法

1. 选择一个值a,问题就变成了在数组中找到和为target-a的组合

2. 为防止组合重复,比如对于[2,3,5,7],和为7的组合可能会出现[2,2,3],[3,2,2],[2,3,2]

3. 为此,限定当选择了下标为i的nums[i],下次只能从i开始往后选择

,不能选择更小下标的值

 

代码如下:

class Solution:
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        res=[]
        path=[]
        n=len(candidates)
        def dfs(path,target,begin):
            if target<0:
                return 
            elif target==0:
                res.append([char for char in path])
                return 
            
            for i in range(begin,n):
                path.append(candidates[i])
                dfs(path,target-candidates[i],i)
                path.pop()
            return
        
        dfs(path,target,0)
        return res

 

 

40. 组合总和II

题目简述:

给定一个候选人编号的集合 candidates 和一个目标数 target ,找出 candidates 中所有可以使数字和为 target 的组合。

candidates 中的每个数字在每个组合中只能使用 一次 。

注意:解集不能包含重复的组合。 

 

思路:

1. 39题的代码稍微改一改

2. 先把candidates排下序

3. 遍历时遇到和上次同样的值时直接跳过

 

代码如下:

class Solution:
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        res=[]
        path=[]
        n=len(candidates)
        candidates.sort()
        def dfs(path,target,begin):
            if target<0:
                return 
            elif target==0:
                #if path not in res:
                res.append([char for char in path])
                return 
            else:
                pre=-1
                for i in range(begin,n):
                    if candidates[i]==pre:
                        continue
                    path.append(candidates[i])
                    dfs(path,target-candidates[i],i+1)
                    path.pop()
                    pre=candidates[i]
                return
        
        dfs(path,target,0)
        return res

 

 

131. 分割回文串

 

题目简述:

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

回文串 是正着读和反着读都一样的字符串。

 

思路:

1. 将字符分为前半段和后半段,下边i以前不包括i的为前半段,其余为后半段

2. i从左往后遍历,判断前半段是不是回文。

3. 如果是回文,将前半段加入path,和后半段的分割结果相加,然后一并加入res

 

代码如下:

class Solution:
    def partition(self, s: str) -> List[List[str]]:
        res=[]

        if len(s)==1:
            return [[s]]
        
        def is_huiwen(arr):
            n=len(arr)
            left=0
            right=n-1
            while left<right:
                if arr[left]==arr[right]:
                    left+=1
                    right-=1
                else:
                    return False
            return True

        def dfs(arr,path):

            n=len(arr)
            if n==0:
                res.append(path[:])
                return
            
            if n==1:
                path.append(arr[0])
                res.append(path[:])
                path.pop()
                return

            for i in (range(1,n+1)):
                if is_huiwen(arr[:i]):
                    path.append(''.join(j for j in arr[:i]))
                    dfs(arr[i:],path)
                    path.pop()
            
            return 
        
        dfs(s,[])

        return res

 

总结:

1. 要学会把问题转换成一个个可迭代的形式

2. 回溯过后,记得恢复原样

 

posted @ 2023-04-13 12:56  blueCP1999  阅读(26)  评论(0)    收藏  举报