目录
- 【力扣】77. 组合
- 题解
- 回溯
- 回溯法三步
- 剪枝优化
【力扣】77. 组合
给定两个整数 n 和 k,返回范围 [1, n] 中所有可能的 k 个数的组合。你可以按任何顺序返回答案。
示例 1:
输入:n = 4, k = 2
输出:
[
[2,4],
[3,4],
[2,3],
[1,2],
[1,3],
[1,4],
]
示例 2:
输入:n = 1, k = 1
输出:
[[1]]
提示:
1 <= n <= 20
1 <= k <= n
题解
暴力思考:k 等于多少就是多少层循环。
//示例中k为2
int n = 4;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
sout(i+" "+j);
}
}
//示例中k为3
int n = 100;
for (int i = 1; i <= n; i++) {
for (int j = i + 1; j <= n; j++) {
for (int u = j + 1; u <= n; n++) {
sout(i+" "+j+" "+u);
}
}
}
回溯
回溯法解决的问题都可以抽象为树形结构(N叉树)。
n 相当于树的宽度,k 相当于树的深度。图中每次搜索到了叶子节点,就找到了一个结果。
回溯法三步
-
递归函数的返回值以及参数
-
回溯函数终止条件
-
单层搜索的过程
void backtracking(参数) {
if (终止条件) {
存放结果;
return;
}
for (选择:本层集合中元素(树中节点孩子的数量就是集合的大小)) {
处理节点;
backtracking(路径,选择列表); // 递归
回溯,撤销处理结果
}
}
import java.util.*;
public class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
public void backtracking(int n, int k, int startIndex) {
// 终止条件
if (path.size() == k) {
//存放结果
result.add(new ArrayList<>(path));
return;
}
//横向遍历
for (int i = startIndex; i <= n; i++) {
//处理节点
path.add(i);
//纵向搜索
backtracking(n, k, i + 1);
//回溯,撤销处理结果
path.removeLast();
}
}
}
剪枝优化
剪枝的地方就在递归中每一层的for循环所选择的起始位置。如果 for 循环选择的起始位置之后的元素个数已经不足需要的元素个数,那么就没有必要搜索了。
- 已经选择的元素个数:
path.size()
; - 还需要的元素个数为:
k - path.size()
; - 在集合 n 中至多要从该起始位置 :
n - (k - path.size()) + 1
,开始遍历
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) // i为本次搜索的起始位置
import java.util.*;
public class Solution {
List<List<Integer>> result = new ArrayList<>();
LinkedList<Integer> path = new LinkedList<>();
public List<List<Integer>> combine(int n, int k) {
backtracking(n, k, 1);
return result;
}
public void backtracking(int n , int k, int startIndex) {
// 终止条件
if (path.size() == k) {
//存放结果
result.add(new ArrayList<>(path));
return;
}
//横向遍历
for (int i = startIndex; i <= n - (k - path.size()) + 1; i++) {// i为本次搜索的起始位置
//处理节点
path.add(i);
//纵向搜索
backtracking(n, k, i + 1);
//回溯,撤销处理结果
path.removeLast();
}
}
}