当前位置: 首页 > ds >正文

LeetCode 216.组合总和 III:回溯算法实现与剪枝优化

目录

  1. 问题描述
  2. 解决思路
    • 回溯法
    • 剪枝优化
  3. 代码实现
  4. 复杂度分析
  5. 示例测试
  6. 总结与扩展

1. 问题描述

给定两个整数 kn,要求找出所有满足以下条件的组合:

  • 组合包含 k 个不同的数字
  • 组合中数字的和等于 n
  • 组合中的数字范围为 [1, 9],且每个数字只能使用一次。

示例:

  • 输入:k = 3, n = 7
  • 输出:[[1, 2, 4]]
  • 解释:1 + 2 + 4 = 7,且没有其他满足条件的三元组。

2. 解决思路

2.1 回溯法

回溯法是解决组合问题的经典方法。其核心思想是:

  1. 递归生成候选解:从候选数字中逐个尝试添加元素。
  2. 剪枝:当发现当前路径无法生成有效解时,提前终止递归。
  3. 回溯撤销选择:在递归返回后,撤销最后一步选择,尝试其他可能性。

2.2 剪枝优化

为了提升算法效率,需要设计剪枝条件:

  1. 总和超过目标值:若当前路径的和已超过 n,停止递归。
  2. 剩余数字不足:若剩余可选的数字不足以填满组合的剩余位置,停止递归。
  3. 避免重复组合:按升序选择数字,确保组合唯一。例如,选择 [1, 2, 4] 后不会生成 [2, 1, 4]

3. 代码实现

import java.util.ArrayList;
import java.util.List;class Solution {public List<List<Integer>> combinationSum3(int k, int n) {List<List<Integer>> result = new ArrayList<>();backtrack(result, new ArrayList<>(), 1, k, n, 0);return result;}private void backtrack(List<List<Integer>> result,List<Integer> path,int start,int k,int n,int currentSum) {// 终止条件:路径长度等于kif (path.size() == k) {if (currentSum == n) {result.add(new ArrayList<>(path));}return;}// 计算当前可以选择的数字的最大起始值int remaining = k - path.size();int maxPossible = 10 - remaining; // 确保剩余数字足够填充剩余位置maxPossible = Math.min(maxPossible, 9); // 不超过9for (int i = start; i <= maxPossible; i++) {// 剪枝:总和超过n时提前终止if (currentSum + i > n) break;path.add(i);backtrack(result, path, i + 1, k, n, currentSum + i); // 递归下一层path.remove(path.size() - 1); // 回溯撤销选择}}
}

关键代码解释

  • backtrack 方法参数

    • result:存储所有合法组合的结果集。
    • path:当前递归路径上的数字组合。
    • start:当前可选的起始数字(避免重复)。
    • k, n:题目输入的条件。
    • currentSum:当前路径的数字和。
  • 剪枝条件

    • maxPossible = 10 - remaining:确保剩余的数字足够填充组合的剩余位置。例如,若还需选2个数字,则起始数字最大为 8(因为 8, 9 是最后两个可选数字)。

4. 复杂度分析

  • 时间复杂度:最坏情况下需要遍历所有组合,时间复杂度为 O(C(9, k)),即从9个数字中选k个的组合数。
  • 空间复杂度:递归调用栈深度为 k,空间复杂度为 O(k)

5. 示例测试

示例 1

输入:k = 3, n = 7
输出:[[1, 2, 4]]

示例 2

输入:k = 4, n = 1
输出:[]
解释:无法找到4个不同的数且和为1

6. 总结与扩展

  • 回溯法的适用性:适合解决组合、排列、子集等问题,通过递归和剪枝平衡效率。
  • 剪枝优化的重要性:合理剪枝可以显著减少无效递归路径。
  • 扩展问题
    • 组合总和 I(数字可重复使用)
    • 组合总和 II(包含重复数字但不可重复使用)

核心收获:通过升序选择数字避免重复,通过预计算最大起始值减少无效遍历。

http://www.xdnf.cn/news/4966.html

相关文章:

  • SpringBoot快速入门WebSocket(​​JSR-356附Demo源码)
  • 为何Google广告频繁拒登?常见原因与解决方法
  • 图表制作-折线图堆叠
  • 允许别的电脑连接我电脑wsl下5001、5002端口
  • 枚举 · 例13-【模板】双指针
  • 《Scala基础》
  • DeepSeek 赋能金融:从智能分析到高效服务的全链路革新
  • WHAT - react-query(TanStack Query) vs swr 请求
  • VUE——自定义指令
  • LabVIEW 2019 与 NI VISA 20.0 安装及报错处理
  • IEEE PRMVAI Workshop 17 | 智能医疗数据分析与应用
  • Baklib云中台赋能企业内容智管
  • Kubernetes外部访问服务全攻略:生产级方案详解
  • 12.hbase 源码构建
  • PFC(Power Factor Correction)功率因数校正电路
  • 金蝶api对接沙箱环境python代码调试
  • SEMI E40-0200 STANDARD FOR PROCESSING MANAGEMENT(加工管理标准)-(一)
  • 【Bluedroid】蓝牙 SDP(服务发现协议)模块代码解析与流程梳理
  • linux动态占用cpu脚本、根据阈值增加占用或取消占用cpu的脚本、自动检测占用脚本状态、3脚本联合套用。
  • java使用MinIO,虚拟机时间异常
  • 低秩适应(LoRA)与量化LoRA(QLoRA)技术解析
  • ‌CDGP|数据治理:探索企业数据有序与安全的解决之道
  • Web 自动化之 HTML JavaScript 详解
  • OpenCV-Python (官方)中文教程(部分一)_Day22
  • 云服务如何简化物联网设备生命周期(How Cloud Services Simplify IoT Device Lifecycles)?
  • 摄像头模组AF、OIS模组
  • 接口-DAO模式
  • 65.微服务保姆教程 (八) 微服务开发与治理实战
  • 车载网络TOP20核心概念科普
  • Go使用Gin写一个对MySQL的增删改查服务