思路
- 要求找出相加之和为n 的k个数字;比如和为7的3个数 1 2 4 。其实就是在1-9内取k个数,并且k个数的和为n
- 与之前的leetcode77不同的是,此处对和值进行了限制
- 需要定义一个全局变量sum,在for循环开始之后,不仅要将 i 加入到path中,还要将sum += i
- 在dfs结束之后,不仅要执行removeLast操作,还要将sum -= i
- 优化:进行剪枝,可以在sum>n 的时候,进行剪枝,已经在for循环寻找上界的时候进行剪枝
- 在寻找上界的时候,思路与leetcode77相同:
- 只不过此处是1-9之间的数字进行选择
// 要选择的元素个数 = k - path.size(),整理得到:
// 搜索起点的上界 = 9 - (k - path.size()) + 1
// 把 i <= n 改成 i <= 9 - (k - path.size()) + 1 :
class Solution {
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<>();
if(k <= 0 || n <= 0 ) return res;
Deque<Integer> path = new ArrayDeque<>();
dfs(k, n, 1, path, res);
return res;
}
private void dfs(int k, int n, int begin, Deque<Integer> path, List<List<Integer>> res){
//终止条件? 当什么时候,将path加入到res中?应该是长度为k,并且sum为n
// 减枝
if (sum > n) {
return;
}
if(path.size() == k && sum == n){
res.add(new ArrayList<>(path));
return;
}
// 减枝 9 - (k - path.size()) + 1
for(int i = begin; i <= 9 - (k - path.size()) + 1; i++){
// 未减枝
// for(int i = begin; i <= 9; i++){
path.addLast(i);
sum += i;
dfs(k, n, i + 1, path, res);
path.removeLast();
sum -= i;
}
}
}
简洁版
class Solution {
int sum = 0;
public List<List<Integer>> combinationSum3(int k, int n) {
List<List<Integer>> res = new ArrayList<>();
if(k <= 0 || n <= 0 ) return res;
Deque<Integer> path = new ArrayDeque<>();
dfs(k, n, 1, path, res);
return res;
}
private void dfs(int k, int n, int begin, Deque<Integer> path, List<List<Integer>> res){
// 减枝
if (sum > n) {
return;
}
if(path.size() == k && sum == n){
res.add(new ArrayList<>(path));
return;
}
// 减枝 9 - (k - path.size()) + 1
for(int i = begin; i <= 9 - (k - path.size()) + 1; i++){
path.addLast(i);
sum += i;
dfs(k, n, i + 1, path, res);
path.removeLast();
sum -= i;
}
}
}