一、找出所有相加之和为 n的 k 个数的组合,且满足下列条件:
- 只使用数字1到9
- 每个数字 最多使用一次
返回所有可能的有效组合的列表。该列表不能包含相同的组合两次,组合可以以任何顺序返回。
示例 1:
输入: k = 3, n = 7
输出: [[1,2,4]]
解释:
1 + 2 + 4 = 7
没有其他符合的组合了。
示例 2:
输入: k = 3, n = 9
输出: [[1,2,6], [1,3,5], [2,3,4]]
解释:
1 + 2 + 6 = 9
1 + 3 + 5 = 9
2 + 3 + 4 = 9
没有其他符合的组合了。
示例 3:
输入: k = 4, n = 1
输出: []
解释: 不存在有效的组合。
在[1,9]范围内使用4个不同的数字,
我们可以得到的最小和是1+2+3+4 = 10,因为10 > 1,没有有效的组合。
提示:
-
2 <= k <= 9 -
1 <= n <= 60
二、
class Solution {
public List<List<Integer>> combinationSum3(int k, int n) {
//k个数的和为n
//数字范围1-9
//每个数字只能用一次
List<List<Integer>> result = new ArrayList<>();
reverse(1, k, n, result, new LinkedList<Integer>());
return result;
}
private void reverse(int start, int k, int n, List<List<Integer>> result, LinkedList<Integer> stack) {
if (n == 0 && k == 0) {
result.add(new ArrayList<>(stack));
return;
}
for (int i = start; i < 10; i++) {
stack.push(i);
reverse(i + 1, k - 1, n - i, result, stack);
stack.pop();
}
}
}
这是一个解决组合总和问题的Java代码示例,问题的要求是从数字1到9中选择k个不同的数,使得它们的和等于n。这个问题使用了递归的方式来解决,其中递归函数 reverse 被用来生成这些组合。
代码中的关键部分如下:
-
public List<List<Integer>> combinationSum3(int k, int n)是入口点方法,接受两个参数,k表示要选择的数字个数,n表示目标和。它初始化了一个空的结果列表result和一个空的栈stack,然后调用reverse方法来寻找符合条件的组合。 -
private void reverse(int start, int k, int n, List<List<Integer>> result, LinkedList<Integer> stack)是实际的递归函数,它用来尝试生成组合。start参数表示当前递归层级的起始数字,即从哪个数字开始尝试选择。k参数表示还需要选择的数字个数。n参数表示目标和。result参数是用于存储符合条件的组合的列表。stack参数是一个栈,用于暂时存储尝试的数字组合。- 如果
n等于0并且k等于0,表示找到了一个符合条件的组合,将该组合添加到结果列表result中,并返回。 - 接下来,使用一个循环从
start(初始为1)到9,依次尝试选择数字。- 在每次选择数字后,将该数字压入栈
stack中,然后递归调用reverse方法,减小k和n,同时增加start。 - 在递归返回后,需要弹出栈顶的数字,以便尝试下一个数字。
- 在每次选择数字后,将该数字压入栈
这个递归过程会不断尝试不同的数字组合,直到找到所有满足条件的组合为止。
最终,combinationSum3 方法返回包含所有满足条件的组合的 result 列表。
三、
当输入 k = 3 和 n = 9 时,该代码将寻找从数字1到9中选择3个不同的数字,使它们的和等于9的所有可能组合。
这是代码的执行过程:
-
combinationSum3(3, 9);调用开始,表示要找到3个数字的组合,使它们的和为9。 -
在
reverse方法中,首先检查n是否等于0且k是否等于0。在这种情况下,n是9,k是3,所以不满足条件,继续执行。 -
然后,通过一个循环,从1到9的数字中依次尝试选择。
- 当选择数字1时,将1添加到栈中,然后递归调用
reverse(2, 2, 8, result, stack);,其中start变为2,k减少为2,n减少为8。- 在第二层递归中,再次通过循环尝试选择数字,但这次的
start是2。 - 当选择数字2时,将2添加到栈中,然后递归调用
reverse(3, 1, 6, result, stack);。- 在第三层递归中,尝试选择数字,但
k已经减少到1,所以只需要找到一个数字,使得n减少为6。 - 重复这个过程,一直尝试不同的数字,直到
k等于0且n等于0。在这种情况下,找到了一个组合 [1, 2, 6],它们的和等于9,因此将这个组合添加到结果列表result中。
- 在第三层递归中,尝试选择数字,但
- 在第二层递归中,再次通过循环尝试选择数字,但这次的
- 当选择数字1时,将1添加到栈中,然后递归调用
-
在第二层递归中,继续尝试其他数字,但没有找到满足条件的组合。
-
回到最初的调用
combinationSum3(3, 9);,在第一层递归中,继续尝试其他数字,直到所有可能的组合都被尝试过。
最终,result 列表将包含满足条件的组合,即 [[1, 2, 6]]。这是从1到9的数字中选择3个不同的数字,使它们的和等于9的唯一可能组合。