題目描述:
給定乙個無重複元素的陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。
candidates 中的數字可以無限制重複被選取。
說明:所有數字(包括 target)都是正整數。
解集不能包含重複的組合。
示例 1:
輸入: candidates =[2
,3,6
,7], target =7,
所求解集為:[[
7],[
2,2,3]]
示例 2:
輸入: candidates =[2
,3,5
], target =8,
所求解集為:[[
2,2,
2,2]
,[2,
3,3]
,[3,5]]
解題思路:做搜尋、回溯問題的套路是畫圖,**其實就是根據畫出的樹形圖寫出來的。
那麼如何畫圖呢?
根據題目中的用例,畫乙個圖,因為是搜尋,因此呈現的是乙個樹形結構圖,並且在這個樹形結構中會體現出遞迴結構。
根據題目中的用例,比對自己畫圖的結果和題目的結果的差異,如果一樣,說明我們的分析沒有錯;如果不一樣,說明我們的分析有誤,一定有哪乙個環節漏掉了或者分析錯誤,根據找到的問題調整演算法。
下面我具體說一下,本來想展示草稿的,奈何本人畫的圖太難看,還是用軟體畫圖給大家看吧。
針對示例 1:
輸入: candidates = [2, 3, 6, 7],target = 7,所求解集為: [[7], [2, 2, 3]]
一開始我畫的圖是這樣的:
思路:以 target = 7 為根結點,每乙個分支做減法。減到 0 或者負數的時候,剪枝。其中,減到 0 的時候結算,這裡 「結算」 的意思是新增到結果集。
我把其中文字的部分去掉了,這樣大家看得清楚一點:
說明:1、乙個藍色正方形表示的是 「嘗試將這個數到陣列 candidates 中找組合」,那麼怎麼找呢?挨個減掉那些數就可以了。
2、在減的過程中,會得到 0 和負數,也就是被我標紅色和粉色的結點:
得到 0 是我們喜歡的,從 0 這一點向根結點走的路徑(很可能只走過一條邊,也算乙個路徑),就是乙個組合,在這一點要做一次結算(把根結點到 0 所經過的路徑,加入結果集)。
得到負數就說明這條路走不通,沒有必要再走下去了。
總結一下:在減的過程中,得到 0 或者負數,就沒有必要再走下去,所以這兩種情況就分別表示成為葉子結點。此時遞迴結束,然後要發生回溯。
畫出圖以後,我看了一下,我這張圖畫出的結果有 4 個 0,對應的路徑是 [[2, 2, 3], [2, 3, 2], [3, 2, 2], [7]],而示例中的解集只有 [[7], [2, 2, 3]],很顯然,我的分析出現了問題。問題是很顯然的,我的結果集出現了重複。重複的原因是
後面分支的更深層的邊出現了前面分支低層的邊的值。
限於我的表達能力有限,大夥意會這句話就可以了,看一看重複的葉子結點 0的路徑,想一想重複的原因,或許你會比我說得更清楚更好。
但是這個問題也不難解決,把候選陣列排個序就好了(想一下,結果陣列排個序是不是也可以去重),後面選取的數不能比前面選的數還要小,即 「更深層的邊上的數值不能比它上層的邊上的數值小」,按照這種策略,剪枝就可以去掉重複的組合。
LeetCode 39 組合總和
給定乙個無重複元素的陣列candidates和乙個目標數target,找出candidates中所有可以使數字和為target的組合。candidates中的數字可以無限制重複被選取。說明 示例 1 輸入 candidates 2,3,6,7 target 7,所求解集為 7 2,2,3 示例 2 ...
leetcode39 組合總和
參考 class solution if next num.size target num next 0 邊界條件 return 對於每個元素,有兩種處理方式,選當前元素或者不選當前元素 psol.push back num next 選當前元素 search num,next,psol,targe...
LeetCode39組合總和
給定乙個無重複元素的陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。說明 所有數字 包括 target 都是正整數。解集不能包含重複的組合。示例 1 輸入 candid...