216. 组合总和 III

113 阅读4分钟

一、找出所有相加之和为 nk 个数的组合,且满足下列条件:

  • 只使用数字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 被用来生成这些组合。

代码中的关键部分如下:

  1. public List<List<Integer>> combinationSum3(int k, int n) 是入口点方法,接受两个参数,k表示要选择的数字个数,n表示目标和。它初始化了一个空的结果列表 result 和一个空的栈 stack,然后调用 reverse 方法来寻找符合条件的组合。

  2. 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 方法,减小 kn,同时增加 start
      • 在递归返回后,需要弹出栈顶的数字,以便尝试下一个数字。

这个递归过程会不断尝试不同的数字组合,直到找到所有满足条件的组合为止。

最终,combinationSum3 方法返回包含所有满足条件的组合的 result 列表。

三、

当输入 k = 3n = 9 时,该代码将寻找从数字1到9中选择3个不同的数字,使它们的和等于9的所有可能组合。

这是代码的执行过程:

  1. combinationSum3(3, 9); 调用开始,表示要找到3个数字的组合,使它们的和为9。

  2. reverse 方法中,首先检查 n 是否等于0且 k 是否等于0。在这种情况下,n 是9,k 是3,所以不满足条件,继续执行。

  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 中。
  4. 在第二层递归中,继续尝试其他数字,但没有找到满足条件的组合。

  5. 回到最初的调用 combinationSum3(3, 9);,在第一层递归中,继续尝试其他数字,直到所有可能的组合都被尝试过。

最终,result 列表将包含满足条件的组合,即 [[1, 2, 6]]。这是从1到9的数字中选择3个不同的数字,使它们的和等于9的唯一可能组合。