LeetCode #39. 组合总和
I. Description:II. Solution:Version 1解题思路:Code:
Version 2解题思路:Code:
I. Description:
II. Solution:
Version 1
解题思路:
该题采用回溯算法的思路进行分析。回溯算法的思路在于:通过枚举法,对所有的可能情况进行遍历。不过枚举的顺序是一条路走到黑,走到走无可走的时候,往前退一步,再尝试之前没走过的下一条路,重复这个过程直到所有的路都走过了。解决回溯问题,实际上就是一个决策树的遍历过程。回溯的实现,主要是依靠
f
o
r
for
for循环和递归的结合。回溯法的关键就是:
一条路走到黑走无可走时回退一步
f
o
r
for
for循环可以给出当前节点下的,所有可以往下走的分支路径;递归意味着继续沿着
f
o
r
for
for循环给出的某个路径向下走一步。如果将递归放到
f
o
r
for
for循环内部,那么for每一次的循环都在给出一个路径之后,进入递归,也就继续往下走了,直到走无可走为止。这样也就实现了一条路走到黑,当递归达到递归出口(走无可走)时,就会实现往前回退一步。回溯算法的模板就是:
res
= []
def backtrack(路径,选择列表
):
if 满足递归结束条件
:
res
.append
(路径
)
return
for 选择
in 选择列表
:
做出选择
backtrack
(路径,选择列表
)
撤销选择
这里的核心就是
f
o
r
for
for循环里面的递归,在递归调用前对下一个可能的节点做出选择,递归调用后取消这个选择,进入下一个循环接着作下一个未走过的选择。从上边模板可以总结出,要完成回溯算法的决策树的遍历过程,只需要考虑三个方面:
路径:你已经做出的选择选择列表:当前节点下剩余的可以作出的选择结束条件:也就是到走无可走时的递归跳出的出口
Code:
cpp
#include <algorithm>
class Solution {
public:
vector
<vector
<int>> combinationSum(vector
<int>& candidates
, int target
) {
sort(candidates
.begin(), candidates
.end());
backtrack(candidates
, target
, 0, 0);
return res
;
}
private:
vector
<vector
<int>> res
;
vector
<int> Path
;
void backtrack(vector
<int> &nums
, int target
, int currentSum
, int startIndex
) {
if(currentSum
> target
){
return;
}
if(currentSum
== target
){
res
.push_back(Path
);
return;
}
for (int i
= startIndex
; i
< nums
.size(); i
++) {
Path
.push_back(nums
[i
]);
currentSum
+= nums
[i
];
backtrack(nums
, target
, currentSum
, i
);
Path
.pop_back();
currentSum
-= nums
[i
];
}
}
};
Version 2
解题思路:
上面解法中递归函数中的参数可以稍微优化一下,其中的 int
t
a
r
g
e
t
target
target, int
c
u
r
r
e
n
t
S
u
m
currentSum
currentSum 这两个参数的用途就是为了判断递归跳出的结束条件用的,因此可以考虑直接取二者的差值,合并为一个int
d
i
f
f
diff
diff参数。
Code:
cpp
class Solution {
public:
vector
<vector
<int>> combinationSum(vector
<int>& candidates
, int target
) {
sort(candidates
.begin(), candidates
.end());
backtrack(candidates
, target
, 0);
return res
;
}
void backtrack(vector
<int> &nums
, int diff
, int startIndex
) {
if (diff
< 0) return;
if(diff
== 0) {
res
.push_back(Path
);
return;
}
for (int i
= startIndex
; i
< nums
.size(); i
++) {
Path
.push_back(nums
[i
]);
backtrack(nums
, diff
- nums
[i
], i
);
Path
.pop_back();
}
}
private:
vector
<vector
<int>> res
;
vector
<int> Path
;
};