文章目录
- 题目
- 方法一:递归+回溯+去重
题目
本题需要注意的就是去重操作因为nums数组里面的元素可能存在重复:
不重复的版本:【LeetCode-中等题】39. 组合总和 不去重版
方法一:递归+回溯+去重
参考讲解视频—回溯算法中的去重,树层去重树枝去重,你弄清楚了没?| LeetCode:40.组合总和II
class Solution {// 递归+ 回溯 candidates 有重复元素 加入标志数组考虑去重List<List<Integer>> res = new ArrayList<>();//最终结果集int len = 0;//数组长度public List<List<Integer>> combinationSum2(int[] candidates, int target) {Arrays.sort(candidates);//对数组排序len = candidates.length;List<Integer> zres = new ArrayList<>();//子结果集int sum = 0; //初始为0int[] flag = new int[len];//设置 标志位 去重int startIndex = 0; //设置遍历开始位置 使得每次只能取自己和自己之后的数组成子结果 避免重复子集dfsback(candidates,zres,sum,target,startIndex,flag);return res;}public void dfsback(int[]candidates, List<Integer> zres,int sum,int target,int startIndex, int[] flag){if(sum == target){res.add(new ArrayList<>(zres));//如果sum == target 收获节点的子集合 再往下遍历肯定大于target 所以直接returnreturn;}if(sum > target) return; //如果sum都大于target 后面就无需遍历了for(int i = startIndex ; i <len ;i++){//题目说同一个 数字可以 无限制重复被选取 那每次遍历都可以从他自己startIndex开始取到数组尾吧 if(flag[i] == 1) continue;if(i>0 && candidates[i] == candidates[i-1] && flag[i-1] == 0) continue;//树层去重 若for循环 后面一个元素和前面一个相同,并且前面一个元素的标志位为0 则执行去重操作,跳过以此元素进行的递归层sum += candidates[i];flag[i] = 1;zres.add(candidates[i]);dfsback(candidates,zres,sum,target,i,flag);//往下递归 这里的i是为了 往下面递归不能取数组前面 的数,不然会出现重复子集 [2,2,3],[2,3,2],[3,2,2]sum -= candidates[i];//回溯复原原值flag[i] = 0;zres.remove(zres.size()-1);}}
}