leetcode 40. 組合總和 II(Java版)

題目描述(題目難度,中等)

給定一個數組 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]
]

來源:力扣(LeetCode)
鏈接:https://leetcode-cn.com/problems/combination-sum-ii
著作權歸領釦網絡所有。商業轉載請聯繫官方授權,非商業轉載請註明出處。

題目求解

使用遞歸求解,遞歸的過程其實就是一個選數的過程,只要遞歸過程中,所選數的和不超過目標數 target,就把所選的數保存到臨時列表中。一旦所選數的和等於 target,就將臨時列表加入結果集。
參考代碼如下:

class Solution {
	public List<List<Integer>> combinationSum2(int[] candidates, int target) {
		List<List<Integer>> result = new ArrayList<>();
		Arrays.sort(candidates); // 去重的第一步
		comSum(candidates, target, result, new ArrayList<>(), 0);
		return result;
	}
    void comSum(int[] can, int tar, List<List<Integer>> res, List<Integer> canRes, int low){
        if(tar == 0){
            res.add(new ArrayList<>(canRes));
            return;
        }
        for(int i = low; i < can.length; ++i){
        	if(i > low && can[i-1] == can[i]) continue; // 去重的第二步
            if(can[i] <= tar){
                canRes.add(can[i]);
                comSum(can, tar-can[i], res, canRes, i+1);
                canRes.remove(canRes.size()-1);
            }else return;
        }
    }
}

遞歸函數最後一個參數表示的是選數的起始位置,i 表示當前所選數的位置,那麼遞歸時最後一個實參置爲 i+1,表示下次會在當前所選數的後面開始選數,這樣就能滿足題目“每個數字在每個組合中只能使用一次”的要求。
但由於 candidates 數組中本身會有重複數字出現,所以單純按 和等於 target 的條件去選,會有重複的組合出現。爲了在遞歸時就去掉重複組合,就需要將 candidates 數組排序,把相同的數聚在一起(其實只要能把相同的數聚在一起,不排序也可以),然後增加判斷條件 i > low && can[i-1] == can[i],就可以將重複組合過濾掉,這個條件一定要細心體會,leetcode 之前的題目三數之和的解法二中也使用了同樣的方法去重。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章