ii 組合總和 組合總和 II(力扣第40題)

2021-10-13 06:29:43 字數 1605 閱讀 1882

題目:

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

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

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

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

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

所求解集為:

[1, 7],

[1, 2, 5],

[2, 6],

[1, 1, 6]

分析:主要對比一下第39題,不同之處在於:第一,陣列中存在重複的元素;第二,每個數字在每個組合中只能使用一次,注意!這裡是每個數字,而不是每種數字,也就是同乙個位置的數字在乙個組合中只能出現一次,但是不同位置的相同數值的數字可以在同乙個組合中同時出現!我們以上面那個示例中的資料作為例子,對搜尋結果的過程進行一次展示,如下圖所示:

在上圖中,每次向下進行一次搜尋,可選取的搜尋範圍都是會發生變化的,因為題目要求乙個數字只能在組合**現一次,所以在一條搜尋路徑中,如果陣列中的某個位置的數字已經使用了,那麼在以後的搜尋中就不能選取了,所以我們為了方便,我們要對原有的陣列進行排序,然後開啟下一次搜尋的遍歷起始元素是當前元素在陣列中索引位置加1,這就能夠保證不會重複使用原有的元素,同時也保證了不會產生上圖中包含黃色葉子結點的路徑的重複組合。

但是,還會有一種重複組合產生的可能,上面第一種重複組合的產生的原因是由於搜尋路徑中元素種類相同但是順序不同所造成的,但是現在第二種重複造成的原因是因為原陣列中存在相同數值的元素,所以就會一定會有相同的路徑產生,這些相同的路徑中元素的順序都是一樣,因為陣列中有重複的元素,所以在搜尋的時候,不同位置的元素就可開啟一條路徑,那麼最終的結果就是一樣的。正如上圖中我沒有畫全的第二個子樹,它和第一棵子樹是一樣的。那麼我們需要去掉這樣的重複,解決辦法:

利用訪問標記陣列,遍歷的搜尋元素的時候,先判斷當前這個元素是否和其在陣列中前乙個位置的元素相等:

如果不相等,那根據回溯的原理我們知道,結束一條路徑的訪問時,其路徑上的結點對應的訪問標記陣列的值都會從下往上被一一置為初始值的。所以那就是重開了一條路徑,而這條重開的路徑最後得到的結果必然和前乙個相同值開啟的路徑得到的結果重複。所以要跳過這個重開的路徑,直接搜尋其他的元素。

**實現:

private list>reslist;public list> combinationsum2(int candidates, inttarget) private void combinationall(int candidates, int target, int start, list curlist,boolean isvisited) for (int i = start; i < candidates.length; i++) if (candidates[i] <=target){

curlist.add(candidates[i]);

isvisited[i]= true;

combinationall(candidates,target-candidates[i],i+1,curlist,isvisited);

isvisited[i]= false;

curlist.remove(curlist.size()-1);

組合總和II

給定乙個無重複元素的陣列 candidates 和乙個目標數 target 找出 candidates 中所有可以使數字和為 target 的組合。candidates 中的數字可以無限制重複被選取。說明 所有數字 包括 target 都是正整數。解集不能包含重複的組合。示例 1 輸入 candid...

組合總和 II

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

組合總和 II

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