【LetMeFly】40.组合总和 II:回溯 + 剪枝 力扣题目链接:https://leetcode.cn/problems/combination-sum-ii/
给定一个候选人编号的集合 candidates
和一个目标数 target
,找出 candidates
中所有可以使数字和为 target
的组合。
candidates
中的每个数字在每个组合中只能使用 一次 。
注意: 解集不能包含重复的组合。
示例 1:
输入: candidates = [10,1,2,7,6,1,5]
, target = 8
,
输出:
[
[1,1,6],
[1,2,5],
[1,7],
[2,6]
]
示例 2:
输入: candidates = [2,5,2,1,2], target = 5,
输出:
[
[1,2,2],
[5]
]
提示:
1 <= candidates.length <= 100
1 <= candidates[i] <= 50
1 <= target <= 30
解题方法:回溯(剪枝) 类似39.组合总和:回溯 + 剪枝 ,但这道题比较困难的地方在于,candidates
中有重复的元素,而答案中不能有重复的数组。
怎么办呢,排序呗。刚开始还和之前一样走正常流程:
如果target已经达到则将当前方案加入答案数组。
如果已超target则直接返回
选当前元素并回溯
不选当前元素
不同之处在于,不选当前元素时,要保证选择的下一个元素和当前元素不同。
例如[4, 4, 5]
,不选第一个4
的话,就不能选第二个4
。
否则的话,可能会出现第一个4和5
、第二个4和5
这两种相同的方案。
时间复杂度$O(len(candidates)^2)$
空间复杂度$O(len(candidates))$
AC代码 C++ 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 class Solution {private : vector<vector<int >> ans; vector<int > now; void dfs (vector<int >& c, int target, int index) { if (!target) { ans.push_back (now); return ; } if (index == c.size () || target < 0 ) { return ; } now.push_back (c[index]); dfs (c, target - c[index], index + 1 ); now.pop_back (); int next = index; while (++next < c.size () && c[next] == c[index]); dfs (c, target, next); }public : vector<vector<int >> combinationSum2 (vector<int >& candidates, int target) { sort (candidates.begin (), candidates.end ()); dfs (candidates, target, 0 ); return ans; } };
Python 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 ''' Author: LetMeFly Date: 2025-01-26 07:58:11 LastEditors: LetMeFly.xyz LastEditTime: 2025-01-26 08:01:59 ''' from typing import List class Solution : def dfs (self, target: int , index: int ) -> None : if not target: self .ans.append([i for i in self .now]) return if index == len (self .c) or target < 0 : return self .now.append(self .c[index]) self .dfs(target - self .c[index], index + 1 ) self .now.pop() next = index + 1 while next < len (self .c) and self .c[next ] == self .c[index]: next += 1 self .dfs(target, next ) def combinationSum2 (self, candidates: List [int ], target: int ) -> List [List [int ]]: candidates.sort() self .c = candidates self .ans = [] self .now = [] self .dfs(target, 0 ) return self .ans
Java 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 import java.util.List;import java.util.ArrayList;import java.util.Arrays;class Solution { private List<List<Integer>> ans; private List<Integer> now; private int [] c; private void dfs (int target, int index) { if (target == 0 ) { ans.add(new ArrayList <>(now)); return ; } if (index == c.length || target < 0 ) { return ; } now.add(c[index]); dfs(target - c[index], index + 1 ); now.remove(now.size() - 1 ); int next = index; while (++next < c.length && c[next] == c[index]); dfs(target, next); } public List<List<Integer>> combinationSum2 (int [] candidates, int target) { Arrays.sort(candidates); c = candidates; ans = new ArrayList <>(); now = new ArrayList <>(); dfs(target, 0 ); return ans; } }
Go 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 package mainimport "sort" func dfs (c []int , target int , now []int , index int , ans *[][]int ) { if target == 0 { *ans = append (*ans, append ([]int {}, now...)) return } if index == len (c) || target < 0 { return } now = append (now, c[index]) dfs(c, target - c[index], now, index + 1 , ans) now = now[:len (now) - 1 ] next := index + 1 for next < len (c) && c[next] == c[index] { next++ } dfs(c, target, now, next, ans) }func combinationSum2 (candidates []int , target int ) (ans [][]int ) { var now []int sort.Ints(candidates) dfs(candidates, target, now, 0 , &ans) return }
同步发文于CSDN和我的个人博客 ,原创不易,转载经作者同意后请附上原文链接 哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/145363298