代码随想录算法训练营第二十五天|216.组合总和III、17.电话号码的字母组合

216. 组合总和 III

思路:

本题就是在[1,2,3,4,5,6,7,8,9]这个集合中找到和为n的k个数的组合。

相对于 77. 组合,无非就是多了一个限制,本题是要找到和为n的k个数的组合,而整个集合已经是固定的了[1,...,9]。

本题k相当于树的深度,9(因为整个集合就是9个数)就是树的宽度

例如 k = 2,n = 4的话,就是在集合[1,2,3,4,5,6,7,8,9]中求 k(个数) = 2, n(和) = 4的组合。

选取过程如图:

216.组合总和III

图中,可以看出,只有最后取到集合(1,3)和为4 符合条件。

剪枝优化:

这道题目,剪枝操作其实是很容易想到了,想必大家看上面的树形图的时候已经想到了。

216.组合总和III1

已选元素总和如果已经大于n(图中数值为4)了,那么往后遍历就没有意义了,直接剪掉。

和回溯算法:组合问题再剪剪枝 (opens new window)一样,for循环的范围也可以剪枝,i <= 9 - (k - path.size()) + 1就可以了。 

代码:

未剪枝优化

class Solution:def combinationSum3(self, k: int, n: int) -> List[List[int]]:result = [] # 初始化结果列表,用于存储所有满足条件的组合path = [] # 初始化当前组合路径列表,用于存储当前正在构建的组合self.backtracking(n, k, 0, 1, path, result) # 调用回溯方法开始搜索return result # 返回结果列表# 回溯方法,递归地搜索所有可能的组合def backtracking(self, targetSum, k, currentSum, startIndex, path, result):if len(path) == k: # 如果当前组合路径的长度等于k,说明已经找到了一个长度为k的组合if currentSum == targetSum: # 检查当前组合的和是否等于目标整数nresult.append(path[:]) # 如果等于,则将当前组合添加到结果列表中。注意:这里使用path[:]而不是path,是为了创建一个新的列表副本,避免后续修改影响结果return # 无论是否满足条件,都返回,结束当前递归分支for i in range(startIndex, 9+1): # 从startIndex开始遍历到9(包括9),因为题目要求组合中的整数范围是1到9 currentSum += i # 将当前整数i添加到当前组合的和中path.append(i) # 将当前整数i添加到当前组合路径中self.backtracking(targetSum, k, currentSum, i + 1, path, result) # 递归调用backtracking方法,继续搜索下一个整数。更新startIndex为i+1,确保不会重复使用相同的整数  # 回溯:撤销当前整数i的选择,以便尝试其他可能的整数currentSum -= i # 从当前组合的和中减去整数ipath.pop() # 从当前组合路径中移除整数i

时间复杂度:分析回溯问题的时间复杂度,有一个通用公式:路径长度×搜索树的叶子数。对于本题,它等于 O(k⋅C(9,k))
空间复杂度:O(k)

剪枝优化 

class Solution:def combinationSum3(self, k: int, n: int) -> List[List[int]]:result = []path = []self.backtracking(n, k, 0, 1, path, result)return resultdef backtracking(self, targetSum, k, currentSum, startIndex, path, result):if currentSum > targetSum:  # 剪枝操作return  if len(path) == k:if currentSum == targetSum:result.append(path[:])for i in range(startIndex, 9 + 1 - (k - len(path)) + 1 ): # 剪枝操作currentSum += ipath.append(i) self.backtracking(targetSum, k, currentSum, i + 1, path, result)currentSum -= ipath.pop()

17. 电话号码的字母组合 

思路:

从示例上来说,输入"23",最直接的想法就是两层for循环遍历了吧,正好把组合的情况都输出了。

如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环.......

大家应该感觉出和77.组合 (opens new window)遇到的一样的问题,就是这for循环的层数如何写出来,此时又是回溯法登场的时候了。

例如:输入:"23",抽象为树形结构,如图所示:

17. 电话号码的字母组合

图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。 

接着就是回溯三部曲:

  • 确定回溯函数参数
  • 确定终止条件
  • 确定单层遍历逻辑

 

代码:

class Solution:def __init__(self):self.letterMap = ["",     # 0"",     # 1"abc",  # 2"def",  # 3"ghi",  # 4"jkl",  # 5"mno",  # 6"pqrs", # 7"tuv",  # 8"wxyz"  # 9] # 创建一个映射表,将数字映射到一组字母self.result = [] # 初始化一个空的结果列表,用于存储所有可能的字母组合self.s = "" # 初始化一个空字符串,用于构建当前的字母组合def letterCombinations(self, digits: str) -> List[str]:if len(digits) == 0: # 如果输入的数字字符串为空,则直接返回空的结果列表return self.resultself.backtracking(digits, 0) # 调用回溯方法开始搜索所有可能的字母组合  return self.result # 返回结果列表# 回溯方法,用于搜索所有可能的字母组合def backtracking(self, digits, index):if index == len(digits): # 如果index等于digits的长度,说明已经处理完所有的数字self.result.append(self.s) # 将当前构建的字符串s添加到结果列表中return # 递归结束,返回digit = int(digits[index]) # 将索引处的数字转换为整数letters = self.letterMap[digit] # 获取当前处理的数字对应的字母组for i in range(len(letters)): # 遍历当前数字对应的每个字母self.s += letters[i] # 将当前字母添加到s中self.backtracking(digits, index + 1) # 递归处理下一个数字self.s = self.s[:-1] # 回溯,撤销之前的选择,即将当前的字母组合s中的最后一个字符删除 
  • 时间复杂度: O(3^m * 4^n),其中 m 是对应四个字母的数字个数,n 是对应三个字母的数字个数
  • 空间复杂度: O(3^m * 4^n)

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.rhkb.cn/news/308851.html

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

vue列表列表过滤

对已知的列表进行数据过滤(根据输入框里面的内容进行数据过滤) 编写案例 通过案例来演示说明 效果就是这样的 输入框是模糊查询 想要实现功能&#xff0c;其实就两大步&#xff0c;1获取输入框内容 2根据输入内容进行数据过滤 绑定收集数据 我们可以使用v-model去双向绑定 …

Java 使用 ant.jar 执行 SQL 脚本文件

Java 使用 ant.jar 执行 SQL 脚本文件&#xff0c;很简单。 在 pom.xml 中导入 ant 依赖 <dependency><groupId>org.apache.ant</groupId><artifactId>ant</artifactId><version>1.10.11</version> </dependency>sql 脚本文件…

【2024】使用Rancher管理k8s集群和创建k8s集群

Rancher管理k8s集群及创建k8s集群。 Rancher版本为:2.8.2目录 rancher管理k8s集群rancher创建k8s集群rancher管理k8s集群 使用rancher管理已经存在的k8s集群。 本部分内容需要自行准备好k8s集群及rancher平台,部署请看本人其他文章 。 登录到rancher平台后,点击集群管理,…

c++修炼之路之vector模拟实现

目录 前言&#xff1a; 一&#xff1a;在STL的开源代码中的vector的实现 二&#xff1a;模拟实现 1.数据成员size()capacity() 2.resizereserve 3.构造函数析构函数赋值重载 4.迭代器[] 5.push_backinserterase迭代器失效问题 三&#xff1a;测试用例和全部代码 接下…

【LAMMPS学习】八、基础知识(1.8)键的断裂

8. 基础知识 此部分描述了如何使用 LAMMPS 为用户和开发人员执行各种任务。术语表页面还列出了 MD 术语&#xff0c;以及相应 LAMMPS 手册页的链接。 LAMMPS 源代码分发的 examples 目录中包含的示例输入脚本以及示例脚本页面上突出显示的示例输入脚本还展示了如何设置和运行各…

【C++庖丁解牛】哈希表/散列表的设计原理 | 哈希函数

&#x1f341;你好&#xff0c;我是 RO-BERRY &#x1f4d7; 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识 &#x1f384;感谢你的陪伴与支持 &#xff0c;故事既有了开头&#xff0c;就要画上一个完美的句号&#xff0c;让我们一起加油 目录 前言1.哈希概念2.哈希冲突…

推荐七个Python效率工具!

为了提高效率&#xff0c;我们在平时工作中常会用到一些Python的效率工具&#xff0c;Python作为比较老的编程语言&#xff0c;它可以实现日常工作的各种自动化。为了更便利的开发项目&#xff0c;这里给大家推荐几个Python的效率工具。 1、Pandas-用于数据分析 Pandas是一个强…

复杂DP算法(动态规划)

复杂DP算法 一、线性DP例题1、鸣人的影分身题目信息思路题解 2、糖果题目信息思路题解 二、区间DP例题密码脱落题目信息思路题解 三、树状DP例题生命之树题目信息思路题解 一、线性DP 例题 1、鸣人的影分身 题目信息 思路 题解 #include <bits/stdc.h> #define endl …

ZISUOJ 数据结构-线性表

题目列表&#xff1a; 问题 A: 逆序链表建立 思路&#xff1a; 可以使用头插法插入所有元素后正序遍历输出或者使用尾插法逆序遍历&#xff0c;推荐使用双链表。这是链表系列的第一个题&#xff0c;那这个题下面的参考题解的各种解法我会尽可能写全一些。 参考题解1&#xff0…

【OTA】STM32-OTA升级——持续更新

【OTA】STM32-OTA升级——持续更新 文章目录 前言一、ymodem串口协议1、Ymodem 协议2、PC3、蓝牙4、WIFI云平台 二、UDS车载协议1.UDS协议 总结 前言 提示&#xff1a;以下是本篇文章正文内容&#xff0c;下面案例可供参考 一、ymodem串口协议 1、Ymodem 协议 STM32 Ymodem …

【I/O】基于事件驱动的 I/O 模型---Reactor

Reactor 模型 BIO 到 I/O 多路复用 为每个连接都创建一个线程 假设我们现在有一个服务器&#xff0c;想要对接多个客户端&#xff0c;那么最简单的方法就是服务端为每个连接都创建一个线程&#xff0c;处理完业务逻辑后&#xff0c;随着连接关闭线程也要销毁&#xff0c;但是…

每日一题(leetcode238):除自身以外数组的乘积--前缀和

不进阶是创建两个数组&#xff1a; class Solution { public:vector<int> productExceptSelf(vector<int>& nums) {int nnums.size();vector<int> left(n);vector<int> right(n);int mul1;for(int i0;i<n;i){mul*nums[i];left[i]mul;}mul1;for…

前端开发攻略---根据音频节奏实时绘制不断变化的波形图。深入剖析如何通过代码实现音频数据的可视化。

1、演示 2、代码分析 逐行解析 JavaScript 代码块&#xff1a; const audioEle document.querySelector(audio) const cvs document.querySelector(canvas) const ctx cvs.getContext(2d)这几行代码首先获取了 <audio> 和 <canvas> 元素的引用&#xff0c;并使用…

Java编程练习之抽象类与抽象方法

使用抽象类和抽象方法时&#xff0c;需要遵循以下原则&#xff1a; 1&#xff09;在抽象类中&#xff0c;可以包含抽象方法&#xff0c;也可以不包含抽象方法&#xff0c;但是包含了抽象方法的类必须被定义为抽象类&#xff1b; 2&#xff09;抽象类不能直接被实例化&#xf…

BugKu:Flask_FileUpload

Flask_FileUpload 解题思路 查看源码&#xff1a; 编写上传的文件 获得结果 小结 文件上传漏洞&#xff1a; 文件上传漏洞是指用户上传了一个可执行的脚本文件&#xff0c;并通过此脚本文件获得了执行服务器端命令的能力。这种攻击方式是最为直接和有效的&#xff0c;“文件上…

探索ERC20代币:构建您的第一个去中心化应用

下面文章中会涉及到该资源中的代码&#xff0c;如果想要完整版代码可以私信我获取&#x1f339; 文章目录 概要整体架构流程技术名词解释ERC20智能合约web3.js 技术细节ERC20合约部署创建前端界面前端与智能合约互连运行DAPP 小结 概要 在加密货币世界中&#xff0c;ERC20代币…

poi-tl的使用(通俗易懂,全面,内含动态表格实现 包会!!)

最近在做项目时候有一个关于解析Html文件&#xff0c;然后将解析的数据转化成word的需求&#xff0c;经过调研&#xff0c;使用poi-tl来实现这个需求&#xff0c;自己学习花费了一些时间&#xff0c;现在将这期间的经验总结起来&#xff0c;让大家可以快速入门 poi-tl的介绍 …

大数据产品有哪些分类?各类里知名大数据产品都有哪些?

随着互联网技术的持续进步和全球数字化转型的推进&#xff0c;我们正处于一个数据爆炸的时代。在这样的大背景下&#xff0c;大数据已经逐渐崭露头角&#xff0c;成为了推动各行各业发展的关键因素和核心资源。大数据不仅仅是指数据的规模巨大&#xff0c;更重要的是它蕴含的价…

Python八股文:基础知识Part2

1. Python中变量的保存和访问 Python中的变量实际上是一个指向对象的引用&#xff0c;每个对象都有一个唯一的标识符&#xff08;即内存地址&#xff09;。对于一些不可变对象&#xff0c;如字符串和整数&#xff0c;因为它们的值不可更改&#xff0c;所以当多个变量引用相同的…

彩虹聚合DNS管理系统源码

聚合DNS管理系统可以实现在一个网站内管理多个平台的域名解析&#xff0c;目前已支持的域名平台有&#xff1a;阿里云、腾讯云、华为云、西部数码、CloudFlare。本系统支持多用户&#xff0c;每个用户可分配不同的域名解析权限&#xff1b;支持API接口&#xff0c;支持获取域名…