目录
- 一、回溯理论基础
- 二、力扣77.组合问题
-
- [2.1 题目](#2.1 题目)
- [2.2 思路](#2.2 思路)
- [2.3 代码](#2.3 代码)
一、回溯理论基础
二、力扣77.组合问题
2.1 题目
2.2 思路
回溯三部曲:递归函数参数及返回值;确定终止条件;单层递归逻辑。
剪枝:
有些不符合条件的就不必去遍历了,即path.size() + 剩余的数的个数已经不满足k的大小了;
修改for循环的终止条件:找到刚好符合k的边界值,即n-(k-path.size())+1.
2.3 代码
第一次出错的代码:
cpp
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
//回溯的组合问题
backTracking(n,k,1);
return res;
}
public void backTracking(int n,int k,int startIndex){
//递归终止条件
if(path.size() == k){
res.add(path);
return;
}
//单层递归逻辑
for(int i = startIndex;i<=n;i++){
path.add(i);
backTracking(n,k,i+1);
//回溯
path.remove(path.size()-1);
}
}
}
修改后的代码:
(注意这里不能直接add path集合,否则都加入的是同一个集合,最后结果集都是同一个path的最终状态)
cpp
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
//回溯的组合问题
backTracking(n,k,1);
return res;
}
public void backTracking(int n,int k,int startIndex){
//递归终止条件
if(path.size() == k){
res.add(new ArrayList<>(path));//注意这里不能直接add path集合,否则都加入的是同一个集合,最后结果集都是同一个path的最终状态
return;
}
//单层递归逻辑
for(int i = startIndex;i<=n;i++){
path.add(i);
backTracking(n,k,i+1);
//回溯
path.remove(path.size()-1);
}
}
}
剪枝后的代码:
cpp
class Solution {
public List<List<Integer>> res = new ArrayList<>();
public List<Integer> path = new ArrayList<>();
public List<List<Integer>> combine(int n, int k) {
//回溯的组合问题
backTracking(n,k,1);
return res;
}
public void backTracking(int n,int k,int startIndex){
//递归终止条件
if(path.size() == k){
res.add(new ArrayList<>(path));//注意这里不能直接add path集合,否则都加入的是同一个集合,最后结果集都是同一个path的最终状态
return;
}
//单层递归逻辑
//剪枝优化
for(int i = startIndex;i<= n-(k-path.size())+1;i++){
path.add(i);
backTracking(n,k,i+1);
//回溯
path.remove(path.size()-1);
}
}
}