# 为什么c++方法不用for循环, [:] 索引拷贝的区别
题目地址:https://leetcode.cn/problems/combination-sum/
# 1. 官方c++解法:
提交测试了几个用例可以通过
```cpp
class Solution {
public:
void dfs(vector<int>& candidates, int target, vector<vector<int>>& ans, vector<int>& combine, int idx) {
if (idx == candidates.size()) {
return;
}
if (target == 0) {
ans.emplace_back(combine);
return;
}
// 直接跳过
dfs(candidates, target, ans, combine, idx + 1);
// 选择当前数
if (target - candidates[idx] >= 0) {
combine.emplace_back(candidates[idx]);
dfs(candidates, target - candidates[idx], ans, combine, idx);
combine.pop_back();
}
}
vector<vector<int>> combinationSum(vector<int>& candidates, int target) {
vector<vector<int>> ans;
vector<int> combine;
dfs(candidates, target, ans, combine, 0);
return ans;
}
};
```
但是
# 2. 对应的Python:
无法得到正确结果,返回结果也为空
```python
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
# 应该使用深度优先遍历 (回溯)算法
if min(candidates) > target:
return []
n = len(candidates)
candidates = sorted(candidates)
# 深度优先所有
def dfs(candidates,target,ret,combine,idx):
# 在当前candidates的idx位置,还需要找到和为target的组合
# ret为当前的最终返回结果, combine为当前的一个组合
# 递归退出条件1: 已经遍历到结尾
if idx == n:
return # 不做任何操作,退出递归调用
# 递归退出条件2: 组合已经凑齐target
if target == 0:
ret.append(combine)
print('ret', ret)
return
# 分支1: 不选择当前的元素
dfs(candidates,target,ret,combine,idx+1)
# 分支2: 选择当前元素
if target >= candidates[idx]: # 注意这里的判断条件是 当前target是否 ,不是当前idx和n的关系
# 选择当前的元素,注意当前元素选了之后还可以再选,所以idx不变
combine.append(candidates[idx])
dfs(candidates,target-candidates[idx],ret,combine,idx)
combine.pop() # 把已经加入combine的元素清除
# print('ret',ret,'com',combine)
# 主函数
ret = []
combine = []
dfs(candidates,target,ret,combine,0)
return ret
```
原因:ret.append(combine) 这里拷贝的是引用,就像用 = 赋值。不是对象,应该使用 ret.append(combine[:])
# 3. 最终的简洁解法
```python
class Solution:
def combinationSum(self, candidates: List[int], target: int) -> List[List[int]]:
# 使用基于深度优先遍历DFS的回溯算法
n = len(candidates)
def huisu(target,currentPath,result,currentSum,currentIndex):
if target == currentSum:
result.append(currentPath[:]) # [:] 很重要!!!会重新开辟一个内存空间,直接 = 赋值只会变成别名
return
if currentSum > target:
return
for i in range(currentIndex,n):
currentSum += candidates[i]
currentPath.append(candidates[i])
huisu(target,currentPath,result,currentSum,i)
currentSum -= candidates[i]
currentPath.pop()
currentPath = [] # 作为全局变量,不要传入
result = [] # 作为全局变量,不要传入
huisu(target,currentPath,result,0,0)
return result
```