leetcode 40組合總和II 回溯

2021-10-10 21:19:37 字數 1393 閱讀 6380

給定乙個陣列 candidates 和乙個目標數 target ,找出 candidates 中所有可以使數字和為 target 的組合。

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

說明:所有數字(包括目標數)都是正整數。

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

示例 1:

輸入: candidates = [10,1,2,7,6,1,5], target = 8,

所求解集為:

[[1, 7],

[1, 2, 5],

[2, 6],

[1, 1, 6]

]示例 2:

輸入: candidates = [2,5,2,1,2], target = 5,

所求解集為:

[[1,2,2],

[5]]

分析:本題是經典的回溯+遞迴的做法,即對於每個數都有選擇和不選擇兩個選擇,但是如果只是這樣選擇,答案會出現重複 比如[2,2],target = 2,的答案會出現兩次。即第一次選取第乙個2,第二次選取第二個2.

為了解決重複的問題,我們可以開創乙個列表,裡面儲存的是一位陣列,陣列下標為0儲存元素的值,下標為1儲存該數出現的次數。

假設不同的數共有m個,因此我們可以遍歷,假設乙個數的出現次數是i,那麼我們就可以考慮對該數選擇0次,1次…i次的情況,分別進行遞迴,這樣就不會出現重複的情況,當當前位置選擇到了m個時,說明已經遞迴結束,沒有多餘的數在可以選,當rest <0時也說明此時無法湊到rest,也可以進行退出。

這樣一來,我們就可以不重複地列舉所有的組合了。

我們還可以進行什麼優化(剪枝)呢?一種比較常用的優化方法是,我們將 freq 根據數從小到大排序,這樣我們在遞迴時會先選擇小的數,再選擇大的數。這樣做的好處是,當我們遞迴到dfs(pos,rest) 時,如果 freq[pos][0] 已經大於 rest,那麼後面還沒有遞迴到的數也都大於 rest,這就說明不可能再選擇若干個和為rest 的數放入列表了。此時,我們就可以直接回溯。

class

solution);

}else

}//開始回溯

dfs(

0,target)

;return ans;

}public

void

dfs(

int pos,

int rest)

else

if(rest <

0|| pos == freq.

size()

)else

//這裡要回溯

//將之前新增到seq中的most個數值刪除掉,到這裡肯定說明前面most個都已經新增到seq中

for(

int i =

1;i <= most;i++)}

}}

leetcode 40 組合總和

給定乙個陣列candidates和乙個目標數target,找出candidates中所有可以使數字和為target的組合。candidates中的每個數字在每個組合中只能使用一次。說明 示例 1 輸入 candidates 10,1,2,7,6,1,5 target 8,所求解集為 1,7 1,2,...

leetcode40 組合總和 II

給定乙個陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的每個數字在每個組合中只能使用一次。說明 所有數字 包括目標數 都是正整數。解集不能包含重複的組合。示例 1 輸入 candidates 1...

LeetCode 40 組合總和 II

給定乙個陣列candidates和乙個目標數target,找出candidates中所有可以使數字和為target的組合。candidates中的每個數字在每個組合中只能使用一次。說明 示例 1 輸入 candidates 10,1,2,7,6,1,5 target 8,所求解集為 1,7 1,2,...