题目
思路
- 思路一:dfs+回溯,遇到这一类相同元素不计算顺序的问题,我们在搜索的时候就需要按某种顺序搜索。具体的做法是:每一次搜索的时候设置 下一轮搜索的起点 index
- 思路二:dfs+回溯+剪枝
思路三:其实这个问题类似于零钱兑换 II问题,因此可以转换为完全背包问题,但是用来找组合不方便,还是dfs+回溯比较方便
代码
//错误写法public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<>();dfs(candidates, target, 0, res, new ArrayList<>());return res;}public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {if (0 == target) res.add(new ArrayList<>(tmp));if (target <= 0) return;for (int i = index; i < candidates.length; i++) {tmp.add(candidates[i]);//失败写法在index,不更新会导致重复结果,用不同起点确保了不会重复dfs(candidates, target - candidates[i], index, res, tmp);tmp.remove(tmp.size() - 1);}}//1.dfs+回溯public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<>();dfs(candidates, target, 0, res, new ArrayList<>());return res;}public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {if (0 == target) res.add(new ArrayList<>(tmp));if (target <= 0) return;for (int i = index; i < candidates.length; i++) {tmp.add(candidates[i]);dfs(candidates, target - candidates[i], i, res, tmp);tmp.remove(tmp.size() - 1);}}//2.dfs+回溯+剪枝public List<List<Integer>> combinationSum(int[] candidates, int target) {List<List<Integer>> res = new ArrayList<>();//排序方便剪枝Arrays.sort(candidates);dfs(candidates, target, 0, res, new ArrayList<>());return res;}public void dfs(int[] candidates, int target, int index, List<List<Integer>> res, List<Integer> tmp) {if (0 == target) res.add(new ArrayList<>(tmp));if (target <= 0) return;for (int i = index; i < candidates.length; i++) {//小于时就剪枝if (target < candidates[i]) return;tmp.add(candidates[i]);dfs(candidates, target - candidates[i], i, res, tmp);tmp.remove(tmp.size() - 1);}}
