# 0039. Combination Sum ###### tags: `Leetcode` `Medium` `回溯` ## 思路 蛮难想的一道题目,所以做的时候直接看答案了,用temp_list存现在的路径,ans存所有的路径,具体执行过程如图 ![](https://i.imgur.com/zdmFFg1.jpg) 但很明显的是如果按这个流程走下去就会有重复的结果[2,2,3][2,3,2][3,2,2], 所以这里就涉及去重,去重的办法就是按照一定的顺序找答案(3sum同理,先排序,之后拿数据的方法是第二个不小于第一个,第三个不小于第二个),本题去重的方法如下图 ![](https://i.imgur.com/bUjZ9mN.jpg) 时间复杂度分析 ![](https://i.imgur.com/RAx7XT1.png) ## Code ```c= class Solution { private: void dfs(vector<vector<int>>& ans, vector<int>& temp_list, int index, vector<int>& candidates, int target){ if(target == 0){ ans.push_back(temp_list); return; } for(int i = index;i < candidates.size();i++){ if(target - candidates[i] < 0){ break; } // if(target - candidates[i] == 0){ // temp_list.push_back(candidates[i]); // ans.push_back(temp_list); // temp_list.pop_back(); // break; // } temp_list.push_back(candidates[i]); dfs(ans, temp_list, i, candidates, target-candidates[i]); temp_list.pop_back(); } } public: vector<vector<int>> combinationSum(vector<int>& candidates, int target) { vector<vector<int>> ans; sort(candidates.begin(),candidates.end()); vector<int> temp_list; dfs(ans,temp_list,0,candidates,target); return ans; } }; ``` 第4 ~ 7行和12 ~ 17行保留一个就好了 ## Result Runtime: 4 ms, faster than **95.95%** of C++ online submissions for Combination Sum. Memory Usage: 10.6 MB, less than **99.85%** of C++ online submissions for Combination Sum. ## Code in Java zxh写的 ```java= class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> ans = new ArrayList<>(); List<Integer> res = new ArrayList<>(); backtrack(candidates, target, res, ans, 0); return ans; } public void backtrack(int[] candidates, int target, List<Integer> res, List<List<Integer>> ans, int idx){ if(target == 0){ List<Integer> list = new ArrayList<>(res); ans.add(list); } if(target<0) return; for(int i = idx;i < candidates.length;i++){ if(i!=idx && candidates[i]==candidates[i-1]) continue; res.add(candidates[i]); backtrack(candidates, target-candidates[i], res, ans, i); res.remove(res.size()-1); } } } ``` szh写的 ```java= class Solution { public List<List<Integer>> combinationSum(int[] candidates, int target) { List<List<Integer>> ans = new ArrayList<>(); Arrays.sort(candidates); int len = candidates.length; Deque<Integer> stack = new ArrayDeque<>(); dfs(candidates, 0, len, target, stack, ans); return ans; } private void dfs(int[] candidates, int index, int len, int target, Deque<Integer> path, List<List<Integer>> ans){ if (target < 0){ return; } if (target == 0){ ans.add(new ArrayList<>(path)); return; } for (int i = index; i < len; i++){ if (target - candidates[i] < 0) break; path.addLast(candidates[i]); // target = target - candidates[i]; dfs(candidates, i, len, target - candidates[i], path, ans); // target += path.getLast(); path.removeLast(); } } } ``` ## 思路 这题就有意思了,需要用到回溯,回溯又需要递归实现。 详细见以下链接,一图胜千言。 https://leetcode-cn.com/problems/combination-sum/solution/hui-su-suan-fa-jian-zhi-python-dai-ma-java-dai-m-2/ 类似题目:131 ## Result 执行用时:3 ms, 在所有 Java 提交中击败了77.36%的用户 内存消耗:38.5 MB, 在所有 Java 提交中击败了86.25%的用户