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!!!