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

力扣刷题笔记-电话号码的字母组合

力扣题目-电话号码的字母组合C++实现

给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
在这里插入图片描述

分析:
这个问题问题本质是“组合枚举”,每个数字可以对应多个字母,每个字母都可能与后面的字母组合形成完整结果。我们要列出所有可能组合,也就是遍历每一种可能的选择。而回溯法恰好就是这样,沿着一条选择路径一直走到底,完成后回退到上一个选择点尝试其他可能,直到所有路径都遍历完。就像走迷宫,刚开始先选择a这个口,沿着 ‘a’ → ‘d’、‘e’、‘f’ 一条条走到底生成 “ad”,“ae”,“af”,然后回到之前的分叉口尝试 ‘b’ → ‘d’,‘e’,‘f’,生成 “bd”,“be”,“bf”,再回去尝试 ‘c’ → “cd”,“ce”,“cf”,直到所有路径走完。
定义一个数字到字母的映射表 mapping,然后用一个字符串 path 来保存当前正在构建的组合,表示回溯过程中不断添加和撤销选择的临时路径。mapping中的下标恰好和数字完全对应,比如mapping[2] 代表 “abc”(数字2对应的字母a、b、c),这样可以快速找到数字对应的字母,在回溯中遍历生成组合。

下标0123456789
数字0123456789
字母abcdefghijklmnopqrstuvwxyz

把输入的数字字符串比如23存在input中,然后先获取到里面的内容’2’和’3’,注意这里获取到的2和3是字符类型的,如果想利用mapping表,必须把这个字符转成整数类型,这样2和3就可以作为mapping的下标找到mapping[2]是’abc’,mapping[3]是’def’。
然后把2对应的abc和3对应的def进行分层处理。
在这里插入图片描述
这里会进行递归处理,index 代表当前正在处理的数字在输入字符串中的索引,每递归一次,index 加 1(index + 1),表示 “处理完当前数字,该处理下一个数字了”。
当 index 等于输入字符串的长度(input.size())时,表示所有数字都已处理完毕。当前构建的组合(path)是一个完整有效的结果,其实这里的index的值也就等于当前构建组合path的长度。每处理完一个数字,就会在 path 中添加一个字母(长度加 1),index的值这时也加1了。这也是为什么终止条件可以用 index == input.size() 来判断 —— 因为此时 path 的长度必然也等于输入长度,已经形成了完整组合。
index初始值为0,先处理第一个数字2。要循环遍历 2’对应的 a/b/c,首先先把数字2对应的a加入到path中,path 本身就像一个栈,用来临时存储 “当前路径”,把a加入路径之后,进入下一层递归(index=1),循环遍历 ‘3’ 对应的 d/e/f,遍历的时候想要再进行下一层递归,但是由于这个时候index=2,已经到了叶子结点了,这时候path里也有两位字母了,可以进行返回。这时第二层3对应的叶子节点如d已经遍历到了,path里是ad,此时要进行回溯,回溯到第一层,相当于把path中的d进行了出栈,现在还剩下第一层的a。回到第 1 层节点a之后,会再去尝试第二层的下一个字母(如 e),然后处理完又会回溯到a去走向下一层的f,直到def全部都遍历完。

class Solution {
public:// 生成数字字符串对应的所有字母组合    vector<string> letterCombinations(string input) {vector<string> res;if (input.empty()) return res;// 数字到字母的映射表(索引对应0-9)        vector<string> mapping = {"", "", "abc", "def", "ghi","jkl", "mno", "pqrs", "tuv", "wxyz"};string path; // 存储当前构建的组合        backtrack(input, 0, path, res, mapping);return res;}
private:// 回溯函数:递归生成所有可能组合    // input:输入的数字串;index:当前处理位置;path:当前组合;res:结果集;mapping:映射表    void backtrack(const string& input, int index, string& path, vector<string>& res, const vector<string>& mapping) {// 终止条件:组合长度等于输入长度时,加入结果集        if (index == input.size()) {res.push_back(path);return;}// 1. 获取当前数字字符       char currentChar = input[index];//当前数字字符并转为整数(如'2'->2),这样可以获取mapping的下标 int digit = currentChar - '0';              // 2. 从映射表获取对应字母(如2->"abc")        string letters = mapping[digit];// 尝试每个字母,递归构建组合后回溯        for (char c : letters) {path.push_back(c);          // 选择字母            backtrack(input, index + 1, path, res, mapping); // 处理下一个数字            path.pop_back();            // 回溯,移除当前字母}}
};

用例子输入23来走一遍代码的流程:

调用 backtrack(“23”, index=0, path=“”, res, mapping)
1.处理第 1 个数字 ‘2’(index=0,letters=“abc”)
1.1 选字母 ‘a’
操作:path.push_back(‘a’) → path=“a”
递归调用 backtrack(“23”, index=1, path=“a”, res, mapping),index变为1准备处理数字3对应的字母

2.处理第 2 个数字 ‘3’(index=1,path=“a”)
2.1 选 ‘d’
操作:path.push_back(‘d’) → path=“ad”
递归调用 backtrack(“23”, index=2, path=“ad”, res, mapping)
index=2 = input.size() → 终止条件 → “ad” 加入 res
返回上一层(index=1,path=“ad”)
回溯:path.pop_back() → path=“a”

2.2 选 ‘e’
操作:path.push_back(‘e’) → path=“ae”
递归调用 index=2 = input.size() → 终止条件→ “ae” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“a”

2.3 选 ‘f’
操作:path.push_back(‘f’) → path=“af”
递归调用 index=2 = input.size() → 终止条件→ “af” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“a”

第 2 层循环结束 → 返回第 1 个数字层(index=0)
回溯:path.pop_back() → path=“”

3.第 1 个数字 '2’继续循环
3.1 选 ‘b’
操作:path.push_back(‘b’) → path=“b”
递归调用 backtrack(“23”, index=1, path=“b”, res, mapping),index变为1准备处理数字3对应的字母

4.处理第 2 个数字 ‘3’(index=1,path=“b”)
4.1 选 ‘d’
操作:path.push_back(‘d’) → path=“bd”
递归调用 index=2 = input.size() → 终止条件→ “bd” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“b”

4.2 选 ‘e’
操作:path.push_back(‘e’) → path=“be”
递归调用 index=2 = input.size() → 终止条件→ “be” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“b”

4.3 选 ‘f’
操作:path.push_back(‘f’) → path=“bf”
递归调用 index=2 = input.size() → 终止条件→ “bf” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“b”

第 2 层循环结束 → 返回第 1 个数字层(index=0)
回溯:path.pop_back() → path=“”

5.第 1 个数字 '2’继续循环
5.1 选 ‘c’
操作:path.push_back(‘c’) → path=“c”
递归调用 backtrack(“23”, index=1, path=“c”, res, mapping),index变为1准备处理数字3对应的字母

6.第 2 个数字 ‘3’(index=1,path=“c”)
6.1 选 ‘d’
操作:path.push_back(‘d’) → path=“cd”
递归调用 backtrack(“23”, index=2, path=“cd”, res, mapping)
index=2 = input.size() → 终止条件 → “cd” 加入 res
返回上一层(index=1,path=“cd”)
回溯:path.pop_back() → path=“c”

6.2 选 ‘e’
操作:path.push_back(‘e’) → path=“ce”
递归调用 index=2 = input.size() → 终止条件→ “ce” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“c”

6.3 选 ‘f’
操作:path.push_back(‘f’) → path=“cf”
递归调用 index=2 = input.size() → 终止条件→ “cf” 加入 res
返回上一层 → 回溯:path.pop_back() → path=“c”

第 2 层循环结束 → 返回第 1 个数字层(index=0)
回溯:path.pop_back() → path=“”
最终结果:
res = [“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”]


文章转载自:

http://lkgBvlZi.sxfnf.cn
http://UtIKCNpA.sxfnf.cn
http://9tsDqEO9.sxfnf.cn
http://XFwCrZ4X.sxfnf.cn
http://1oGkGbvP.sxfnf.cn
http://rgjZ7wWk.sxfnf.cn
http://PGyCjn56.sxfnf.cn
http://M3Hh2o6F.sxfnf.cn
http://NScFLQoD.sxfnf.cn
http://JL7DRYUl.sxfnf.cn
http://ObUltFv6.sxfnf.cn
http://yJlInPyz.sxfnf.cn
http://BVNxeF3E.sxfnf.cn
http://1QPsjeF8.sxfnf.cn
http://1fNPSD9t.sxfnf.cn
http://0RlPUd1g.sxfnf.cn
http://lHW62wVx.sxfnf.cn
http://HwB2qKVY.sxfnf.cn
http://mjBVNb8E.sxfnf.cn
http://sF1o9Bba.sxfnf.cn
http://NNZNbKzq.sxfnf.cn
http://6NVyHnOk.sxfnf.cn
http://5pkyZgUi.sxfnf.cn
http://kcPi6EKj.sxfnf.cn
http://pS6h7iZZ.sxfnf.cn
http://WWpqfts0.sxfnf.cn
http://oxXxmrQC.sxfnf.cn
http://UieN40g6.sxfnf.cn
http://z1RAzr5p.sxfnf.cn
http://PEP28uwy.sxfnf.cn
http://www.dtcms.com/a/381060.html

相关文章:

  • 基于arduino的视频监控土壤灌溉系统
  • 【硬件-笔试面试题-90】硬件/电子工程师,笔试面试题(知识点:DCDC开关电源的效率计算)
  • 快速理解并记住Python中的可变与不可变对象
  • Netty 调优篇:实战配置、性能监控与常见坑
  • ZYNQ7020+AD9361裸机驱动验证
  • 【超简单】后端入门案例-基于SpringBoot+MyBatis-plus+MySQL图书管理系统
  • 【C++】:list容器全面解析(超详细)
  • Java 笔记 OCA 备考Checked Exception(受检异常)
  • DAY 26 函数专题1:函数定义与参数-2025.9.13
  • MySQL的基础和进阶与运维
  • 看到手就亮灯 防夹手视觉光栅
  • QT M/V架构开发实战:M/V架构的初步认识
  • 4.2-中间件之MySQL
  • 基于hiprint的票据定位打印系统开发实践
  • 批量获取虾皮商品数据:开放API接口操作详解
  • @JsonFormat 如何在get请求中日期字段不报错还能使用
  • C/C++ 标准库中的 `strspn` 函数
  • 关闭click for mouse control
  • C语言打印爱心
  • Notion-Folder-Opener | 一个极简、稳定的本地“链接→打开文件/文件夹”工具
  • Linux系统 SELinux 安全管理与故障排查
  • Vue:后端服务代码解析
  • 仓颉语言与C++对比深度解析:从特性对比到语言选型及实践
  • 嵌入式 - ARM6
  • uniapp | 快速上手ThorUI组件
  • 容器使用绑定挂载
  • 智能排班系统哪个好?从L1到L4,AI排班软件选型指南
  • CentOS7.9 离线升级内核
  • 杨辉三角**
  • Android「Global / Secure / System」三大命名空间全局设置项总结