LeeCode.216 组合总和 Ⅲ

题目

LeetCode.216 组合总和 Ⅲ

解题思路

回溯思路

全局变量

  • List<Intetger> path:用于记录每一次递归的搜索结果;
  • List<List<Intetger>> result:保存最终结果;
  • int curSum:保存当前 path 中元素的和;

回溯函数的作用

  • 回溯函数 backtracking 用于判断 path 中的元素是否满足题目要求

递归参数和返回值

  • 参数:
    1. int k:k 个数。题目给定的 k,用于判断递归是否结束;
    2. int n:k 个数之和为 n。题目给定的 n,用于判断递归是否结束;
    3. int startIndex:每一层循环的开始下标,避免产生重复组合;
  • 返回值:
    1. void:没有返回值,结果存在 path 和 result 中;
public void backtracking(int k, int n, int startIndex) { }

回溯结束条件

  • 当 path 中的元素个数等于 k 时:
    • 如果 curSum 等于 n,就将 path 加入到 result 中,返回上一层;
    • 否则的话直接返回;
if(path.size() == k) {
	if(curSum == n) result.add(new ArrayList(path));
	return;
}

单次回溯逻辑

  • 为了避免产生重复组合,我们可以设定:在每一次循环中,从 startIndex 开始,往后进行组合。即循环从 startIndex 开始,循环范围是 [startIndex, 9]
  • 在循环体中,首先先判断,(n - (curSum + i)) 是否 < 0,如果条件成立,则直接返回(剪枝):
    • curSum + i:表示在 path 中加入元素 i 后,path 的所有元素之和
    • (n - (curSum + i)) < 0:表示加上 i 之后,path 所有元素之和大于 n;
      • 此时 i 已经无法满足题目的条件;
      • i 之后的元素是递增的,所以 i 之后的元素也都无法满足题目条件;
      • 因此本层循环可以直接结束;
  • 如果条件不成立,则将 i 加入 path 中,并把 curSum 加上 i,然后判断此时的path是否满足递归结束条件:
    • 若不满足,则进入下一层递归,下一次循环起点为 i + 1;
    • 若满足,则返回后把 i 从 path 中移除,并把 curSum 减去 i。然后 i++,进入下一次循环。
for(int i = startIndex; i <= 9; i++) {
	if(n - (curSum + i) < 0) return;
   	curSum += i;
   	path.add(i);	
    backtracking(n, k, i + 1);
   	path.remove(path.size() - 1);	// 在回溯法中,有加入就要有弹出
   	curSum -= i;
}

完整代码(核心代码模式)

class Solution {

    List<Integer> path = new ArrayList<>();
    List<List<Integer>> result = new ArrayList<>();
    int curSum = 0;

    public List<List<Integer>> combinationSum3(int k, int n) {
        backtracking(n, k, 1);
        return result;
    }

    public void backtracking(int n, int k, int startIndex) {
        if(path.size() == k) {
            if(curSum == n) result.add(new ArrayList(path));
            return;
        }

        for(int i = startIndex; i <= 9; i++) {
            if(n - (curSum + i) < 0) return;
            curSum += i;
            path.add(i);
            backtracking(n, k, i + 1);
            path.remove(path.size() - 1);
            curSum -= i;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值