程式碼隨想錄演算法訓練營第二十三天| leetcode39. 組合總和、leetcode40.組合總和II、leetcode131.分割回文串

小方呀0524發表於2024-11-12

1 leetcode39. 組合總和

題目連結:39. 組合總和 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:帶你學透回溯演算法-組合總和(對應「leetcode」力扣題目:39.組合總和)| 回溯法精講!_嗶哩嗶哩_bilibili

思路:跟之前差不多,就是將他的迴圈改一下,但是我發現有重複的數值了,不知道如何刪除

1.1 自己的思路

錯誤

  1. 基本思路是完全可以實現的,但是有重複的數值,不知道怎麼刪除,但是也就淺淺記錄一下這個方法吧
class Solution:
    def __init__(self):
        self.result =[]
        self.path = []
        self.num = 0
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.backtracking(candidates,target)
        return self.result
    def backtracking(self,candidates,target):
        if sum(self.path[:])>target:
            return
        if sum(self.path[:])==target:
            self.result.append(self.path[:])
            return self.result
        for i in range(len(candidates)):
            self.path.append(candidates[i])
            self.backtracking(candidates,target)
            self.path.pop()

1.2 影片的思路

看影片過程中然後反思自己的程式碼,做出來了

原因:索引的起始位置出現了錯誤,更改以後就正確了

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

1.3 剪枝的方法

class Solution:
    def __init__(self):
        self.result =[]
        self.path = []
        self.num = 0
    def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
        self.backtracking(candidates,target,0)
        return self.result
    def backtracking(self,candidates,target,index):
        candidates.sort()
        if sum(self.path[:])>target:
            return
        if sum(self.path[:])==target:
            self.result.append(self.path[:])
            return self.result
        for i in range(index,len(candidates)):
            if target-candidates[i]<0:
                break
            self.path.append(candidates[i])
            self.backtracking(candidates,target,i)
            self.path.pop()

1.4 本題小結

  1. 這道題我也算是真正自己做啦,就是當時忘記去重,不知道怎麼加後來自己想了以後也寫出來啦
  2. 這道題的剪枝方法,我感覺排序會浪費時間,覺得沒有最佳化太多

2 leetcode40.組合總和II

題目連結:40. 組合總和 II - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:回溯演算法中的去重,樹層去重樹枝去重,你弄清楚了沒?| LeetCode:40.組合總和II_嗶哩嗶哩_bilibili

思路:照葫蘆畫瓢,結果發現我翻車了,就是有重複的

2.1 回溯的方法

這裡的判斷條件挺有意思的,從當前位置的後一個去比較,比較他們的值是否有重複的,然後進行去重,確實這個去重是我沒有想到的地方

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

2.2 使用一個列表的去重方法

這種方法,確實還是自己的資歷不夠很多時候知道要幹啥,但是我確實也寫不出來

class Solution:
    def __init__(self):
        self.result = []
        self.path = []
    def combinationSum2(self, candidates: List[int], target: int) -> List[List[int]]:
        candidates.sort()
        used = [False]*len(candidates)
        self.backtracking(candidates,target,0,used)
        return self.result
    def backtracking(self,candidates,target,startindex,used):
        if sum(self.path[:])>target:
            return
        if sum(self.path[:])==target:
            self.result.append(self.path[:])
            return self.result
        for i in range(startindex,len(candidates)):
            if i>0 and candidates[i]==candidates[i-1] and used[i-1]==False:
                continue
            self.path.append(candidates[i])
            used[i] =True
            self.backtracking(candidates,target,i+1,used)
            self.path.pop()
            used[i] =False

2.3 本題小結

  1. 這道題的關鍵點在於去重,對於python去重其實可以保證這個數比當前位置的值大,且與這個數值相等就好了
  2. 這種used的去重方法,相對而言更適用於所有方法吧

3 leetcode131.分割回文串

題目連結:131. 分割回文串 - 力扣(LeetCode)

文章連結:程式碼隨想錄

影片連結:帶你學透回溯演算法-分割回文串(對應力扣題目:131.分割回文串)| 回溯法精講!_嗶哩嗶哩_bilibili

思路:嗯,就是看不懂吧,,

3.1 影片後的思路

晚上看影片有點暈的感覺,就看講解做了,嗯,覺得自己好懶多定義一個函式都不想,哈哈哈哈哈哈哈,其實定義一個新的函式就可以對其進行一個使用了

class Solution:
    def __init__(self):
        self.result = []
        self.path = []
    
    def partition(self, s: str) -> List[List[str]]:
        self.backtracking(s,0)
        return self.result

    def backtracking(self,s,startindex):
        if startindex==len(s):
            self.result.append(self.path[:])
            return
        for i in range(startindex,len(s)):
            if self.isPalindrom(s,startindex,i):
                self.path.append(s[startindex:i+1])
                self.backtracking(s,i+1)
                self.path.pop()

    def isPalindrom(self,s,left,right):
        while left<right:
            if s[left]!=s[right]:
                return False
            left +=1
            right-=1
        return True          

3.2 本題小結

  1. 這道題,成功被自己的思維打敗了,居然就是多定義一個函式並且在結尾處再對資料進行處理就好了
  2. 晚上了,不知道寫啥,但是覺得真的不難

4 今日小結

  1. 第一道題是對之前題目的一個再回顧吧,我覺得剪枝沒有太多的最佳化
  2. 第二題當時困住我的地方是不知道如何去重,後來發現其實在python中去重的方法挺多的
  3. 第三題,主要是真的不知道如何分割之類的問題,不過後來好好去思考了,跟著題目也算是可以做了吧

相關文章