回溯法与迭代法详解:如何从手机数字键盘生成字母组合

在这篇文章中,我们将详细介绍如何基于手机数字键盘的映射,给定一个仅包含数字 2-9 的字符串,输出它能够表示的所有字母组合。这是一个经典的回溯算法问题,适合初学者理解和掌握。

问题描述

给定一个数字字符串,比如 digits = "23",手机数字键盘的映射如下:
在这里插入图片描述

2 -> "abc"
3 -> "def"
4 -> "ghi"
5 -> "jkl"
6 -> "mno"
7 -> "pqrs"
8 -> "tuv"
9 -> "wxyz"

我们需要找到所有可能的字母组合。举个例子:

"23" -> ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]

17. 电话号码的字母组合 - 力扣(LeetCode)

1. 问题分析

从问题的角度看,这是一个组合问题。手机键盘上的每个数字对应一组字母,我们要找到给定数字的所有字母组合。关键在于如何构建这些组合。我们可以通过回溯法或者迭代法来解决。

1.1 回溯法的思路

回溯算法是递归算法的一种,适合用来枚举所有可能的结果。在这个问题中,回溯的关键点是从第一个数字开始,遍历所有可能的字母组合,逐步构建字符串,直到所有数字都被处理完毕。

具体步骤如下:

  1. 选择:我们从 digits 中每个数字开始,找到对应的字母集。
  2. 递归:对于字母集中的每个字母,我们递归地去构建字符串,直到遍历完所有的数字。
  3. 回退:在递归过程中,构建的字符串达到一定长度后,我们会回退(撤销上一步操作),尝试其他的可能性。
1.2 多种解法
  • 回溯法:利用递归去枚举所有可能的组合。复杂度为 O ( 3 n ) O(3^n) O(3n) O ( 4 n ) O(4^n) O(4n),取决于输入的数字个数。
  • 迭代法:使用队列的方式逐步构造出所有的字母组合。每处理一个数字,都会将当前已有的组合与对应的新字母结合。

接下来我们详细介绍这两种解法。


2. 解法一:回溯法(Backtracking)

2.1 解题思路

回溯算法的基本思路是递归地构建可能的组合,并在递归结束时撤销选择。具体来说,我们会从第一个数字开始,对应的字母集选择一个字母,然后递归处理下一个数字。

回溯的步骤:

  1. 如果已经构建的字符串长度等于 digits 的长度,我们就将它加入结果集。
  2. 否则,继续处理下一个数字。
  3. 每次递归返回时,撤销上一次的选择,尝试下一个字母。
2.2 代码实现
#include <iostream>
#include <vector>
#include <unordered_map>using namespace std;class Solution {
public:vector<string> ans;  // 存储结果string combination = "";  // 当前的字母组合void backtrack(const string& digits, unordered_map<char, string>& phone, int idx) {if (idx == digits.size()) {  // 当达到数字字符串的长度时ans.push_back(combination);  // 将组合加入结果集return;}char digit = digits[idx];  // 获取当前数字const string& letters = phone[digit];  // 获取当前数字对应的字母集for (char letter : letters) {  // 遍历字母集中的每个字母combination += letter;  // 做出选择backtrack(digits, phone, idx + 1);  // 递归处理下一个数字combination.pop_back();  // 回溯,撤销选择}}vector<string> letterCombinations(string digits) {if (digits.empty()) return {};  // 边界情况处理,空输入返回空数组// 建立数字到字母的映射unordered_map<char, string> phone = {{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"},{'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};// 调用回溯函数backtrack(digits, phone, 0);return ans;  // 返回结果}
};
2.3 详细解释
  1. 递归终止条件:当索引 idx 达到 digits 的长度时,说明我们已经构造了一个完整的字母组合,将其加入结果集。
  2. 递归过程:对于当前数字,找到对应的字母集,遍历字母集中的每一个字母,加入到当前的组合字符串中,然后递归处理下一个数字。
  3. 回溯撤销选择:在递归返回后,我们调用 combination.pop_back() 撤销上一次递归中加入的字符,回退到上一个状态,从而尝试下一个字母。
2.4 示例模拟过程
  • 输入:digits = "23"
    • 递归过程:
      1. 处理第一个数字 2,对应的字母集是 ['a', 'b', 'c']
      2. 选中字母 'a',递归处理下一个数字 3,对应的字母集是 ['d', 'e', 'f']
      3. 选中字母 'd',完成组合 'ad',将其加入结果集。
      4. 回退到字母 'a',选择下一个字母 'e',构造组合 'ae',继续加入结果集。
      5. 继续这种方式,构造出 'af',然后回退选择字母 'b'
      6. 重复上述过程直到遍历所有字母,得到组合 ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]

3. 解法二:迭代法(使用队列)

3.1 解题思路

另一种方法是利用队列。我们可以使用一个队列来逐步生成组合:

  1. 从数字字符串的第一个数字开始,把对应的字母放入队列。
  2. 对于每一个数字,取出队列中所有的已有组合,然后在每个组合后附加当前数字对应的每一个字母,形成新的组合,再放回队列。
  3. 当处理完所有的数字时,队列中保存的就是所有可能的组合。
3.2 代码实现
#include <iostream>
#include <vector>
#include <unordered_map>
#include <queue>using namespace std;class Solution {
public:vector<string> letterCombinations(string digits) {if (digits.empty()) return {};  // 边界情况处理,空输入返回空数组// 建立数字到字母的映射unordered_map<char, string> phone = {{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"},{'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};queue<string> q;  // 定义一个队列来保存组合q.push("");  // 先往队列中放入一个空字符串// 遍历输入数字字符串中的每个数字for (char digit : digits) {int n = q.size();  // 记录当前队列的大小const string& letters = phone[digit];  // 获取当前数字对应的字母集for (int i = 0; i < n; i++) {  // 对于当前队列中每个已有组合string current = q.front();  // 取出队首元素q.pop();  // 移除队首// 对当前数字的每个字母,将其加到已有组合的后面for (char letter : letters) {q.push(current + letter);  // 将新组合放回队列}}}// 最终队列中的所有元素就是结果vector<string> ans;while (!q.empty()) {ans.push_back(q.front());q.pop();}return ans;}
};
3.3 示例讲解
  • 输入:digits = "23"
    1. 初始化队列:q = [""]
    2. 处理

第一个数字 2,对应的字母集 ['a', 'b', 'c']。将每个字母加到队列中的每一个已有组合(当前为空字符串 ""),得到队列 q = ["a", "b", "c"]
3. 处理第二个数字 3,对应的字母集 ['d', 'e', 'f']。将每个字母加到队列中的每一个已有组合,得到 q = ["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]
4. 最终队列中的元素就是结果。


4. 总结

  • 回溯法:通过递归逐步构建可能的组合,并在递归结束后撤销选择,时间复杂度接近 O ( 3 n ) O(3^n) O(3n) O ( 4 n ) O(4^n) O(4n),取决于数字对应的字母数量。回溯算法的优点是易于实现,适合处理这种组合问题。

  • 迭代法(队列):通过队列逐步构建组合,时间复杂度也是 O ( 3 n ) O(3^n) O(3n) O ( 4 n ) O(4^n) O(4n)。虽然有时实现起来可能比递归稍微复杂,但它在一些情况下的性能表现会更好。

对于新手来说,回溯法可能是更直观的解法,因为它的思路清晰,非常适合处理类似的组合问题。

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

如若内容造成侵权/违法违规/事实不符,请联系一条长河网进行投诉反馈,一经查实,立即删除!

相关文章

TikTok流量不好是为什么?是网络没选对吗?

很多人发现他们的TikTok视频观看量不高&#xff0c;点赞和分享率也低&#xff0c;就会开始怀疑是不是网络选择不当导致了这一问题。虽然网络确实是导致流量不佳的一大原因之一&#xff0c;但也不能忽视其他因素&#xff0c;包括内容质量、时机选择、互动参与等方面。本文将揭示…

桌面运维转网络要做什么准备,高级网工学习路线分享_运维转网络工程师好转岗吗

如果你的船不进来&#xff0c;请游过去。 做过桌面运维的朋友都知道&#xff0c;这个岗位相当于做牛做马。我做桌面运维的时候要修监控门禁&#xff0c;消防报警广播音响&#xff0c;还要懂暖通空调下水管道疏通&#xff0c;电梯保养与维护&#xff0c;我听到有些同行还得会修桌…

数据采集崩溃恢复:保障业务稳定运行的关键技术特性

一、场景描述 在当今信息时代&#xff0c;数据已成为企业核心竞争力的重要组成部分。对于许多企业而言&#xff0c;数据的采集、处理和分析至关重要。然而&#xff0c;在数据采集和处理过程中&#xff0c;系统崩溃或故障是无法避免的现象。如何在数据采集过程中确保数据的完整…

计量校准公司对校准工程师,会有什么资质要求?

计量校准是指利用一些计量校准工具&#xff0c;对机器、仪器等进行测量和校准。来实现基本功能的正常使用。计量校准安排&#xff0c;是指根据委托方的要求&#xff0c;按照计量器具校准标准&#xff0c;向社会提供计量器具校准服务的安排。今天&#xff0c;我们就来看看计量校…

腾讯音乐:从 Elasticsearch 到 Apache Doris 内容库升级,统一搜索分析引擎,成本直降 80%

导读&#xff1a; 为满足更严苛数据分析的需求&#xff0c;腾讯音乐借助 Apache Doris 替代了 Elasticsearch 集群&#xff0c;统一了内容库数据平台的内容搜索和分析引擎。并基于 Doris 倒排索引和全文检索的能力&#xff0c;支持了复杂的自定义标签计算&#xff0c;实现秒级查…

24最新新手入门指南:Stable Diffusion!

前言 Stable Diffusion&#xff0c;一款新兴的开源AI绘画软件&#xff0c;正逐渐成为数字艺术家和爱好者的新宠。它的强大功能让用户能够轻松创造出令人印象深刻的数字艺术作品。 无论你是专业艺术家还是艺术新手&#xff0c;Stable Diffusion都为你提供了一个探索创造力的新…

如何卸载电脑上的软件?电脑软件彻底删除的3个常见方法(强力卸载注册表)

电脑使用久了&#xff0c;难免会遇到卡顿&#xff0c;运行不流畅的情况&#xff0c;这属于正常现象。造成电脑卡顿的很大部分原因就是因为电脑安装了太多软件了&#xff0c;特别是一些“来路不明”的软件容易影响电脑运行速度。使用电脑时&#xff0c;定期清理电脑垃圾&#xf…

这本书有亿点厉害!带你快速入门扩散模型,从原理到实战!!-《扩散模型从原理到实战》

AIGC爱好者有福了&#xff0c;快看看这本《扩散模型》 书名&#xff1a;《扩散模型&#xff1a;从原理到实战》 作者&#xff1a; 李忻玮等 适合人群&#xff1a; 对扩散模型感兴趣的AI研究人员&#xff1b;有使用AIGC生成图片需求的从业人员&#xff1b;对stable Diffusi…

小米13工程固件预览 修复底层分区 修复nv损坏主板电阻 默认开启diag端口

机型名称 :小米 13【用于以下型号的小米机型:2211133G, 2211133C】机型代号 :fuxi 小米13搭载高通骁龙 8 Gen2八核处理器,预装miui14操作系统;后置5000万像素主镜头+1200万像素超广角镜头+1000万像素长焦镜头,前置3200万像素摄像头;搭载4500毫安时容量不可拆卸电池…

邮件营销案例成功技巧:如何打动目标客户?

邮件营销案例分析成功策略&#xff1f;有哪些优质邮件营销案例&#xff1f; 企业不仅能够与目标客户建立联系&#xff0c;还能有效地推动销售和提升品牌忠诚度。MailBing将通过多个邮件营销成功案例&#xff0c;探讨如何打动目标客户&#xff0c;并分享一些实用的技巧。 邮件…

Rad Studio 12.2 出来了

RAD Studio 12.1之后5个月&#xff0c;RAD Studio 12之后10个月&#xff0c;新发布的RAD Studio12.2加入了客户的反馈&#xff0c;利用人工智能能力的编码支持&#xff0c;64-bit版本的编译器等先进的功能&#xff0c;为应用开发提供更强有力的支持。 本文介绍了RAD Studio 12…

JS 运算符

目录 1. 赋值运算符 2. 一元运算符 2.1 自增 2.1.1 前置自增 2.1.2 后置自增 2.1.3 前置与后置自增对比 3. 比较运算符 3.1 字符串比较 4. 逻辑运算符 4.1 案例 5. 运算符优先级 1. 赋值运算符 2. 一元运算符 2.1 自增 2.1.1 前置自增 2.1.2 后置自增 2.1.3 前置与后…

圈子系统APP小程序H5该如何设置IM?

搭建圈子系统的常见问题,以及圈子论坛系统的功能特点 社交圈子论坛系统的概念 圈子小程序源码 多客圈子系统 圈子是什么软件 跟进圈一个系统的软件 为圈子系统APP小程序H5设置IM&#xff08;即时通讯&#xff09;&#xff0c;需要遵循一系列步骤来确保通讯功能的稳定、安全和高…

magic-html : 通用HTML数据提取器!DocAI:从非结构化文档中提取结构化数据!强大、快速、开源的微信机器人底层框架:wcf.js!

magic-html : 通用HTML数据提取器&#xff01;DocAI&#xff1a;从非结构化文档中提取结构化数据&#xff01;强大、快速、开源的微信机器人底层框架&#xff1a;wcf.js&#xff01; magic-html : 通用HTML数据提取器 magic-html提供了一套工具&#xff0c;能够轻松地从HTML中…

水凝胶制造新突破,DIW 技术来助力,打印参数很关键

大家好&#xff01;今天我们来了解一篇《Innovations in hydrogel-based manufacturing: A comprehensive review of direct ink writing technique for biomedical applications》发表于《Advances in Colloid and Interface Science》。水凝胶因其独特性质在多领域备受关注&a…

STL之set、map的使用

STL之set、map 1. 序列式容器和关联式容器2. set系列的使⽤参考文档链接&#xff1a;2.1 set的介绍&#xff08;2&#xff09;set的增删查2.2 multiset的介绍 3 map3.1 参考文档3.2 map类的介绍3.3 pair类型介绍3.4 map的构造3.6 map的数据修改3.7 multimap和map的差异 1. 序列…

解锁未来新技能——揭秘人工智能工程师证书!

为进一步贯彻落实中共中央印发《关于深化人才发展体制机制改革的意见》和国务院印发《关于“十四五”数字经济发展规划》等有关工作的部署要求&#xff0c;深入实施人才强国战略和创新驱动发展战略&#xff0c;加强全国数字化人才队伍建设&#xff0c;持续推进人工智能从业人员…

MySQL 【日期】函数大全(二)

DATE_ADDDATE_FORMATDATE_SUBDATEDIFFDAYDAYNAMEDAYOFMONTHDAYOFWEEK 1、DATE_ADD DATE_ADD(date, value) &#xff1a;在指定的日期/时间上加上指定的时间间隔加并返回新的日期/时间。 DATE_ADD(date, value) DATE_ADD(date, INTERVAL value unit) date&#xff1a;需要操作…

Agent的四种设计模式,从零实现Agent框架

让大模型返回json格式&#xff0c;方便直接处理数据。 LLM支持json格式&#xff1a; def chat(self, user\_prompt, json\_modeFalse): kwargs {} if json\_mode: kwargs\["response\_format"\] \ {"type": "json\_object"} completion …

深圳大学-Java程序设计-选实验1 基础知识练习

实验目的与要求&#xff1a; 实验目的&#xff1a;掌握Java程序设计开发环境的搭建&#xff0c;编写简单Java Project&#xff0c;掌握编译、运行等基本步骤和命令。 实验要求&#xff1a; (1).下载、安装"Java SE Development Kit 20.0.2"最新的版本&#xff0c;需…