(Java) LeetCode 40. Combination Sum II —— 組合總和 II


Given a collection of candidate numbers (candidates) and a target number (target), find all unique combinations in candidates where the candidate numbers sums to target.

Each number in candidates may only be used once in the combination.

Note:

  • All numbers (including target) will be positive integers.
  • The solution set must not contain duplicate combinations.

Example 1:

Input: candidates = [10,1,2,7,6,1,5], target = 8,
A solution set is:
[
  [1, 7],
  [1, 2, 5],
  [2, 6],
  [1, 1, 6]
]

Example 2:

Input: candidates = [2,5,2,1,2], target = 5,
A solution set is:
[
  [1,2,2],
  [5]
]

 

LeetCode 39. Combination Sum —— 組合總和的升級版。還是想象成圖來幫助理解。和第39題相比本題有兩個變化。第一,本題有重復節點;第二,每個節點只能用一次,即沒有自環。結合對39代碼注釋的理解,稍稍更改即可得到本題的解題思路:

如何處理自環問題?每次搜索新路徑的時候都從其下一個節點開始,而不是從它本身開始;

如何處理去重問題?每次回溯的時候,剛剛被剔除的節點不能在任何時候再被重新加入到路徑上。如何處理這個“任何時候”呢?要么用map標記被剔除的節點直到路徑搜索結束,要么應用排序,將所有有相同出權值的節點都放到一起,這樣可以方便找到下一個出權值不同的節點。

想完這兩個不同點,這道題就解決了。詳見代碼注釋。

 


Java

class Solution {
    public List<List<Integer>> combinationSum2(int[] candidates, int target) {
        List<List<Integer>> res = new ArrayList<>();
        if (candidates == null || candidates.length == 0 || target < 0) return res;
        List<Integer> list = new ArrayList<>();
        Arrays.sort(candidates); //排序,使得尋找相同出權值的節點變得容易
        get(candidates, target, 0, list, res);
        return res;
    }
    
    private void get(int[] candidates, int target, int i, List<Integer> list, List<List<Integer>> res) {
        if (i > candidates.length || target < 0) return; //因為沒有自環,所以每次都是從下一個節點開始搜索,要添加一個條件判斷節點仍在圖中
        if (target == 0) { //滿足條件,添加至結果集
            res.add(new ArrayList<>(list)); 
            return;
        }
        for (int p = i; p < candidates.length; p++) { 
            list.add(candidates[p]); //添加節點到路徑
            get(candidates, target - candidates[p], p+1, list, res); //因為沒有自環,所以每次搜索更新路徑權值后的下一個節點
            list.remove(list.size()-1); //回溯,將當前節點從路徑中剔除
            while (p < candidates.length - 1 && candidates[p] == candidates[p+1]) p++; //因為存在重復節點,所以已經被剔除的節點不能再被放回到路徑中
        }
    }
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM