程式碼隨想錄演算法訓練營第23天 | 39.組合總和 40.組合總和Ⅱ 131.分割回文串

Y荷兰豆Y發表於2024-06-28

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()

相關文章