算法:
相比于上一题,数组candidates有重复元素,而要求不能有重复的组合,所以相对于39.组合总和 (opens new window)难度提升了不少。
如何去重?
先把candidates排序,让重复的元素都在一起
单层递归时,
if ( i > startindex && candidates[i] == candidates[i - 1] ) {continue;}
调试过程:
class Solution {
//全局变量path和resultList<List<Integer>> result = new LinkedList<>();List<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {
//`int[] candidates` 表示一个整数数组,可以包含多个整数元素。你可以通过`candidates[0]`、`candidates[1]`等方式访问数组中的不同元素。
//int target` 则表示一个单独的整数变量,只能存储一个整数值。if (candidates == null) return result;Arrays.sort(candidates);backtracking(candidates, target, 0, 0);return result;}void backtracking(int[] candidates, int target, int sum, int startindex){//确定终止条件if (sum > target) return;if (sum == target) {result.add(new LinkedList(path));return;}//单层递归逻辑for (int i = startindex; i < candidates.length && sum <= target; i++){if (i > startindex && candidates[i] == candidates[i-1]) continue;path.add(candidates[i]);sum += candidates[i];backtracking(candidates, target, sum, i);//回溯sum -= candidates[i];path.removeLast();}}
}
原因:没去重
单层递归中,应该改成i+1了
backtracking(candidates, target, sum, i+1);
正确代码:
class Solution {
//全局变量path和resultList<List<Integer>> result = new LinkedList<>();List<Integer> path = new LinkedList<>();public List<List<Integer>> combinationSum2(int[] candidates, int target) {
//`int[] candidates` 表示一个整数数组,可以包含多个整数元素。你可以通过`candidates[0]`、`candidates[1]`等方式访问数组中的不同元素。
//int target` 则表示一个单独的整数变量,只能存储一个整数值。if (candidates == null) return result;
//排序Arrays.sort(candidates);backtracking(candidates, target, 0, 0);return result;}void backtracking(int[] candidates, int target, int sum, int startindex){//确定终止条件if (sum > target) return;if (sum == target) {result.add(new LinkedList(path));return;}//单层递归逻辑for (int i = startindex; i < candidates.length && sum <= target; i++){
//去重if (i > startindex && candidates[i] == candidates[i-1]) continue;path.add(candidates[i]);sum += candidates[i];backtracking(candidates, target, sum, i+1);//回溯sum -= candidates[i];path.removeLast();}}
}
时间空间复杂度:
- 时间复杂度: O(n * 2^n),注意这只是复杂度的上界,因为剪枝的存在,真实的时间复杂度远小于此
- 空间复杂度: O(target)