LeetCode39. 组合总和
☆☆☆代码: 排序剪枝后效率更高 ~
class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> res = new ArrayList<>(); Arrays.sort(candidates); dfs(candidates,0, target, new ArrayList<>(), res); // Arrays.sort(candidates); // dfs1(candidates, 0, target, new ArrayList<>(), res); return res; } // 难点是如何去除重复的组合 //(每次i从0开始搜索) 去重前 : [ [2,2,2,2],[2,3,3],[3,2,3],[3,3,2],[3,5],[5,3] ] //(每次 i 从index开始搜索)去重后 : [ [2,2,2,2],[2,3,3],[3,5] ] // 优化前: 4ms // 优化后(排序+剪枝):2ms private void dfs(int[] nums,int start, int target, List<Integer> list, List<List<Integer>> res) { // if (target < 0) return; // 排序剪枝后不需要加,因为小于0的部分被剪枝 if (target == 0) { res.add(new ArrayList<>(list)); return; } for (int i = start; i < nums.length; i++) { if (target < nums[i]) break; // 排序后剪枝,后面全是大于target的,直接跳出 list.add(nums[i]); // 由于每一个元素可以重复使用,下一轮搜索的起点依然是 i dfs(nums, i,target - nums[i], list, res); list.remove(list.size() - 1); } } /** * 回溯写法2:做选择 * 优化前:4ms * 优化(排序+剪枝):2ms */ private void dfs1(int[] nums, int index, int target, List<Integer> list, List<List<Integer>> res) { if (index == nums.length) return; if (target == 0) { res.add(new ArrayList<>(list)); return; } // if (target < 0) return; // 优化前剪枝 if (target < nums[index]) return; //优化后剪枝 candidates排序后,target小于当前的值就不用往后算了 list.add(nums[index]); dfs1(nums, index, target - nums[index], list, res); list.remove(list.size() - 1); dfs1(nums, index + 1, target, list, res); } }