1、题干
给定两个整数 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
2、解题
方法一:(回溯算法)
这是一道类似全排列的问题,给定范围,给出要求,求出可能得所有组合,可以使用回溯算法求解。
回溯算法要点:
明确不变的量,明确本趟组装的临时变量,明确结果集合。递归处理;
递归的终止条件(一般是临时变量符合要求),添加结果集;非终止的情况下循环处理,先添加元素向后发起,之后在删除元素向前回溯。
套用上面的公式,代码示例如下。
代码示例:
public static List<List<Integer>> combine(int n, int k) {
List<List<Integer>> result = new ArrayList<>(); // 结果集
List<Integer> tempList = new ArrayList<>(); // 当前趟的组合
int index = 1; // 添加元素的位置
goAndBack(n, k, tempList, index, result); // 固定部分(n,k),临时可变部分(tempList,index),结果集(result)
return result;
}
private static void goAndBack(int n, int k, List<Integer> tempList, int index, List<List<Integer>> result) {
if (tempList.size() == k) { // 递归终止条件
result.add(new ArrayList<>(tempList)); // 注意tempList需要删除元素进行回溯处理,所用new ArrayList<>包裹处理。
return;
}
for (int i = index; i <= n; i++) { // 使用index为起始位置,防止添加相同的元素。
// 临时部分处理后,递归向后处理
tempList.add(i); // 临时部分tempList添加元素
goAndBack(n, k, tempList, i + 1, result); // 下一个元素位置index从之后的i+1开始,防止添加重复元素
// 删除元素,回溯处理。删除最后的元素
tempList.remove(tempList.size() - 1);
}
}
向阳前行,Dare To Be!!!