Day 26| 39. 組合總和 、 40.組合總和II 、 131.分割回文串

forrestr發表於2024-06-18
  1. 組合總和

本題是 集合裡元素可以用無數次,那麼和組合問題的差別 其實僅在於 startIndex上的控制

題目連結/文章講解:https://programmercarl.com/0039.組合總和.html
影片講解:https://www.bilibili.com/video/BV1KT4y1M7HJ
給定一個無重複元素的陣列 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。
candidates 中的數字可以無限制重複被選取。

思考

這道題的特點是可以重複選取。
因此for迴圈內遍歷的時候,start_index = i

class Solution:
    def __init__(self):
        self.path = []
        self.res_list_all = []
        self.sum = 0
    def backtracking(self,candidates,target,start_index):
        if self.sum == target:
            self.res_list_all.append(self.path[:])
            return 
        elif self.sum > target:
            return 
        else:
            for i in range(start_index,len(candidates)):
                self.path.append(candidates[i])
                self.sum+=candidates[i]
                self.backtracking(candidates,target,i)
                self.path.pop()
                self.sum-=candidates[i]
                
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.backtracking(candidates,target,0)
        return self.res_list_all

排序後,回溯的過程可以剪枝,同一層,前面的數和已經超了的話,後面的就不用再試了,因為後面的數更大。

class Solution:
    def __init__(self):
        self.path = []
        self.res_list_all = []
        self.sum = 0
    def backtracking(self,candidates,target,start_index):
        if self.sum == target:
            self.res_list_all.append(self.path[:])
            return 
        elif self.sum > target:
            return 
        else:
            for i in range(start_index,len(candidates)):
                if self.sum+candidates[i] > target:
                    break
                self.path.append(candidates[i])
                self.sum+=candidates[i]
                self.backtracking(candidates,target,i)
                self.path.pop()
                self.sum-=candidates[i]
                
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        self.backtracking(candidates,target,0)
        return self.res_list_all

40.組合總和II

本題開始涉及到一個問題了:去重。

注意題目中給我們 集合是有重複元素的,那麼求出來的 組合有可能重複,但題目要求不能有重複組合。

題目連結/文章講解:https://programmercarl.com/0040.組合總和II.html
影片講解:https://www.bilibili.com/video/BV12V4y1V73A

給定一個候選人編號的集合 candidates 和一個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

candidates 中的每個數字在每個組合中只能使用 一次 。

注意:解集不能包含重複的組合。

思考

這道題的難點是要在回溯中去重,即去除重複的組合。
兩種方法:

  1. 需要定義一個used陣列。
    used[i - 1] == true,說明同一樹枝candidates[i - 1]使用過
    used[i - 1] == false,說明同一樹層candidates[i - 1]使用過

    2. 判斷條件增加i>start_index
    兩種方案都需要先排序才能去重。

方案二的方法

class Solution:
    def __init__(self):
        self.res = []
        self.res_all = []
        self.sum = 0
    def backtracking(self,candidates,target,start_index):
        if self.sum > target:
            return
        if self.sum == target:
            self.res_all.append(self.res[:])
            return
        for i in range(start_index,len(candidates)):
            if i > start_index and (candidates[i-1] == candidates[i]):
                continue
            self.sum+=candidates[i]
            self.res.append(candidates[i])
            self.backtracking(candidates,target,i+1)
            self.res.pop()
            self.sum-=candidates[i]
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        self.backtracking(candidates,target,0)
        return self.res_all

131.分割回文串

本題較難,大家先看影片來理解 分割問題,明天還會有一道分割問題,先打打基礎。

https://programmercarl.com/0131.分割回文串.html
影片講解:https://www.bilibili.com/video/BV1c54y1e7k6
給定一個字串 s,將 s 分割成一些子串,使每個子串都是迴文串。

返回 s 所有可能的分割方案。

示例: 輸入: "aab" 輸出: [ ["aa","b"], ["a","a","b"] ]

思考

分割問題本質上也是求組合問題。start_index表示分割線。

def is_huiwen(s):
    i = 0
    j = len(s)-1
    while i<j:
        if s[i]==s[j]:
            i+=1
            j-=1
        else:
            return False
    return True
class Solution:
    def partition(self, s: str) -> List[List[str]]:
        def backtracking(s,star_index):
            if star_index == len(s):
                res.append(path[:])
                return
            for i in range(star_index,len(s)):
                if is_huiwen(s[star_index:i+1]):
                    path.append(s[star_index:i+1])
                    backtracking(s,i+1)
                    path.pop()
        path = []
        res = []
        backtracking(s,0)
        return res   

相關文章