LeetCode 0216.组合总和 III:回溯(剪枝) OR 二进制枚举

devtools/2024/11/14 11:52:16/

【LetMeFly】216.组合总和 III:回溯(剪枝) OR 二进制枚举

力扣题目链接:https://leetcode.cn/problems/combination-sum-iii/

找出所有相加之和为 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

方法一:二进制枚举(选与不选)

一共 9 9 9个数,每个数选与不选一共有 2 9 = 512 2^9=512 29=512种情况。

我们只需要使用一个二进制数一一枚举这 512 512 512种情况即可。

二进制数的每一位代表每个数的选与不选,对于某种情况,只需要判断是否恰好为 k k k个数,以及是否恰好和为 n n n即可。

  • 时间复杂度 O ( C × 2 C ) O(C\times2^C) O(C×2C),其中 C = 9 C=9 C=9
  • 空间复杂度 O ( C ) O(C) O(C)

AC代码

C++
class Solution {
public:vector<vector<int>> combinationSum3(int k, int n) {vector<vector<int>> ans;int to = 1 << 9;for (int i = 0; i < to; i++) {if (__builtin_popcount(i) != k) {continue;}vector<int> thisSolution;int thisCnt = 0;for (int j = 0; j < 9; j++) {if (i & (1 << j)) {thisCnt += j + 1;thisSolution.push_back(j + 1);}}if (thisCnt == n) {ans.push_back(thisSolution);}}return ans;}
};
Python
# from typing import Listclass Solution:def combinationSum3(self, k: int, n: int) -> List[List[int]]:ans = []for i in range(1 << 9):if i.bit_count() != k:  # Python 3.9.4中似乎无此函数continuethisSolution = []thisCnt = 0for j in range(9):if i & (1 << j):thisCnt += j + 1thisSolution.append(j + 1)if thisCnt == n:ans.append(thisSolution)return ans

方法二:回溯+剪枝(DFS)

写一个函数dfs(k, n, index)来求所有“从[index,9]范围内选k个数使得和为n”的情况。

  • 如果k = 0 && n == 0,则说明当前方案为一个可行方案,计入答案中且返回
  • 如果index > n || index == 10 || k <= 0,则终止(剪枝/递归终止条件)

这样,就只有选与不选index这两种情况:

  1. 不选index:直接递归调用dfs(k, n, index + 1)
  2. index:将index加入当前选择方案的数组中、递归调用dfs(k - 1, n - index, index + 1)、将index从当前方案中移除(回溯)

以上

  • 时间复杂度 O ( ( C k ) × k ) O(\begin{pmatrix}C\\ k\end{pmatrix}\times k) O((Ck)×k),其中 C = 9 C=9 C=9 ( C k ) \begin{pmatrix}C\\ k\end{pmatrix} (Ck)为组合数从 C C C个数里面选 k k k
  • 空间复杂度 O ( C ) O(C) O(C)

AC代码

C++
class Solution {
private:vector<vector<int>> ans;vector<int> now;// 从[index,9]范围内选k个数使得和为nvoid dfs(int k, int n, int index) {if (!k && !n) {ans.push_back(now);return;}if (index > n || index == 10 || k <= 0) {return;}// not choosedfs(k, n, index + 1);// choosenow.push_back(index);dfs(k - 1, n - index, index + 1);now.pop_back();}
public:vector<vector<int>> combinationSum3(int k, int n) {dfs(k, n, 1);return ans;}
};

小数据情况下,方法一的实际执行效果也许会优于方法二。

Python
# from typing import Listclass Solution:def dfs(self, k: int, n: int, index: int) -> None:if not k and not n:self.ans.append(self.now[:])returnif index > n or index == 10 or k <= 0:returnself.dfs(k, n, index + 1)self.now.append(index)self.dfs(k - 1, n - index, index + 1)self.now.pop()def combinationSum3(self, k: int, n: int) -> List[List[int]]:self.ans = []self.now = []self.dfs(k, n, 1)return self.ans

同步发文于CSDN和我的个人博客,原创不易,转载经作者同意后请附上原文链接哦~
Tisfy:https://letmefly.blog.csdn.net/article/details/138033273


http://www.ppmy.cn/devtools/14009.html

相关文章

全世界IT人苦竞业久矣!美国FTC宣布全面废除员工竞业协议

2023 年 1 月&#xff0c;美国联邦贸易委员会&#xff08;FTC&#xff09;发布声明称&#xff0c;拟在全国范围禁止用人单位与雇员签订竞业禁止性条款。当地时间 4 月 23 日&#xff0c;FTC 宣布全面禁止所有员工&#xff08;包括高级管理人员&#xff09;签署新的竞业禁止协议…

光接入网络的超宽带半导体光放大器

添加图片注释&#xff0c;不超过 140 字&#xff08;可选&#xff09; 新颖的双有源层结构获得宽增益光谱&#xff0c;应用于多波单纤双向光放大 ----翻译Xiao Sun等人2016年撰写的文章&#xff0c;文中给出了宽光谱SOA的一种新颖的结构设计方法和仿真结果&#xff0c;但并未给…

中仕公考:教师的工资组成是怎样的?

1、基本工资 ① 岗位工资&#xff0c;这部分工资是和职称挂钩的&#xff0c;职称越高工资越高; ② 教龄工资&#xff0c;这部分工资会随着教龄增长而逐步增长; 2、绩效工资: 基础性绩效(看职称) 奖励性绩效: 班主任及领导津贴、教龄津贴、课时津贴、考勤津贴、精神文明奖…

Web前端 Javascript笔记5

1、事件类型 ①、HTML事件 事件说明load当页面完全加载后在window上面触发&#xff0c;或当框架集加载完毕后在框架集上触发&#xff1b;unload当页面完全卸载后在window上面触发&#xff0c;或当框架集卸载后在框架集上触发&#xff1b;select当用户选择文本框&#xff08;i…

笔记 | 嵌入式系统概论

1 嵌入式系统简介 1.1 嵌入式系统的定义 根据美国电气与电子工程师学会&#xff08;IEEE&#xff1a;Institute of Electrical and Electronics Engineers )的定义&#xff0c;嵌入式系统是用于控制、监视或辅助操作机器和设备的装置(原文: devices used to control, monitor…

07 内核开发-避免命名冲突经验技巧分享

07 内核开发-避免命名冲突经验技巧分享 目录 07 内核开发-避免命名冲突经验技巧分享 1.如何在内核开发过程中&#xff0c;避免命名冲突 2. 背景 3.避免方法 4.了解下 文件/proc/kallsyms 5.总结 课程简介&#xff1a; Linux内核开发入门是一门旨在帮助学习者从最基本的…

redis主从

主从复制&#xff1a; 主从复制是Redis中常用的一种数据复制方式&#xff0c;它通过将一个Redis服务器&#xff08;主节点&#xff09;的数据复制到多个其他Redis服务器&#xff08;从节点&#xff09;上来实现数据的备份和读写分离。主从复制的主要作用是提高数据的可用性和读…

javaweb-SpringBoot基础

什么是SpringBoot Spring的官网(https://spring.io) Spring的简介&#xff1a;Spring makes Java simple。 Spring Boot 可以帮助我们非常快速的构建应用程序、简化开发、提高效率 。 SpringBootWeb快速入门 需求&#xff1a; 基于SpringBoot的方式开发一个web应用&#x…