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

LeetCode 17. 电话号码的字母组合

题目描述

给定一个仅包含数字2-9的字符串,返回所有它能表示的字母组合。

答案可以按任意顺序返回。

数字到字母的映射与电话按键相同:

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

注意:1不对应任何字母。

例如:

输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

初始思路

一开始我把这题当成了全排列问题处理。

我的想法是:用onPath记录已经选择过的字母,然后在每一层递归中遍历所有digits对应的字母,避免同一个字母重复选择。

这个思路的问题在于:它套用了全排列模板,但这题不是全排列。

全排列关注的是:

从一堆候选元素里选出一个排列,每个元素通常只能用一次。

而电话号码的字母组合关注的是:

每个数字位置,只能从这个数字对应的字母中选一个。

所以这题不需要onPath,也不应该每层遍历所有数字。

解题思路

这题的关键是先明确递归函数的含义。

定义:

dfs(i):当前正在决定 digits[i] 这一位应该选择哪个字母

对于digits = "23"

第 0 位数字是 2,只能从 "abc" 中选一个 第 1 位数字是 3,只能从 "def" 中选一个

搜索过程是:

a -> d/e/f b -> d/e/f c -> d/e/f

也就是每一层只处理当前位置digits[i],而不是重新遍历所有数字。

递归流程:

1. 如果 digits 为空,直接返回空列表 2. dfs(i) 表示正在决定第 i 位数字对应的字母 3. 找到 digits[i] 对应的字符串 letters 4. 遍历 letters 中的每个字符 c 5. 把 c 放入 path[i] 6. 递归 dfs(i + 1) 7. 当 i == digits.length 时,path 已经填满,加入答案

代码实现

class Solution { String[] mapping = { "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz" }; List<String> ans = new ArrayList<>(); public List<String> letterCombinations(String digits) { if (digits.length() == 0) { return ans; } char[] path = new char[digits.length()]; dfs(digits.toCharArray(), 0, path); return ans; } public void dfs(char[] digits, int i, char[] path) { if (i == digits.length) { ans.add(new String(path)); return; } int idx = digits[i] - '0'; for (char c : mapping[idx].toCharArray()) { path[i] = c; dfs(digits, i + 1, path); } } }

为什么不用 onPath

onPath常用于全排列问题,用来表示某个元素在当前路径里是否已经被使用过。

比如全排列中:

nums = [1, 2, 3]

同一个排列里,1不能重复使用。

但这题不是这样。每一位数字都独立选择一个对应字母。

比如:

digits = "22"

合法结果包括:

aa, ab, ac, ba, bb, bc, ca, cb, cc

如果使用onPath禁止重复字母,aabbcc就会被错误排除。

所以这题的核心不是“字母能不能重复使用”,而是:

当前位置的数字,决定了当前位置可以选择哪些字母。

易错点

1. 把题目误套成全排列模板

错误方向是:

每一层遍历所有 digits,再遍历每个 digit 对应的字母。

这样会打乱数字位置和字母选择之间的关系。

正确方向是:

第 i 层只处理 digits[i]

2. 错误使用 onPath

这题不需要记录某个字母是否已经选过。

每个数字位置只负责选自己的字母,递归进入下一层时自然会处理下一个数字。

3. 漏掉空字符串特判

digits = ""时,题目要求返回:

[]

如果不特判,递归一开始就会满足:

i == digits.length

然后把空字符串加入答案,返回:

[""]

这是不符合题意的。

复杂度分析

n = digits.length()

每个数字最多对应 4 个字母,所以组合数量最多是4^n

  • 时间复杂度:O(n * 4^n)。最多有4^n个组合,每个组合转成字符串需要O(n)
  • 空间复杂度:O(n)。递归栈和path长度都是n;如果把返回结果也计入空间,则为O(n * 4^n)

复盘

这题最重要的是不要把所有回溯题都套成同一个模板。

全排列的模型是:

每一层从所有未使用元素中选一个。

电话号码字母组合的模型是:

每一层只处理当前位置的数字,从这个数字对应的字母中选一个。

所以递归定义应该从“当前处理第几个数字”出发:

dfs(i):决定 digits[i] 这一位的字母

只要这个定义清楚,path[i] = cdfs(i + 1)i == digits.length这些代码就都很自然。

Tips

这题可以记住一句话:

一个数字位置选一个对应字母,不是从所有字母里做排列。

遇到回溯题时,先判断当前层到底是在“填位置”,还是在“选或不选”,不要直接套模板。

http://www.jsqmd.com/news/1304464/

相关文章:

  • STM32调试连接故障全解析:从No Target Connected到稳定SWD通信
  • 2026年8月层流净化车间/工业净化车间服务公司选哪家_优诺系统集成有限公司 - 行业平台推荐
  • GPT Pro性能跃迁深度解析:从推理优化到MoE架构的技术揭秘与实战指南
  • 2026北京装修行业获客新思路:家装/工装/设计工作室如何通过AIGEO低成本
  • 深入解析Cyclone IV FPGA逻辑单元(LE)架构与设计优化
  • Next.js生活工具前端架构全景:状态流、路由与组件通信
  • 2026年8月广州漏水检测/广州漏水施工公司推荐几家_广州执盾建筑防水工程有限公司 - 品牌宣传支持者
  • 2026年 不锈钢门厂家推荐排行榜,304不锈钢门,简易不锈钢门,自建房不锈钢门,匠心铸造安全之选! - 优企名品
  • Linux连接跟踪(conntrack)原理、实践与性能调优指南
  • 音频剧制作技术全解析:从TTS合成到多轨混音的工程实践
  • 数字逻辑电路入门:从布尔代数到FPGA实践
  • GPT-5.5 516令牌断崖现象:成因、影响与工程应对策略
  • 主流 Agent 架构分析
  • 2026年 织带印刷厂家推荐排行榜,运动护具织带logo印刷,服饰辅料织带印刷加工,运动绑带印刷源头厂家精选! - 优企名品
  • 计算机毕业设计之程序设计基础视频学习系统的设计与实现
  • 靠谱的亚洲EMBA择校指南,适配民营企业家进阶
  • 2026年精选:新乡真空上料机优质厂家——建一智能装备的硬实力解码 - 装修教育财税推荐2026
  • Umi-OCR:免费离线OCR软件,轻松提取图片文字
  • UniApp生命周期全解析:从原理到实战,解决跨端开发核心难题
  • 2026年阳台遮阳棚厂家推荐榜单:电动伸缩/固定式铝合金遮阳棚,户外防雨防晒隔热优选品牌解析 - 优企名品
  • 2026年度10款降AI率软件红黑榜!优缺点全公开,达标率硬核对标行业天花板
  • 大众EA888烧机油治理方案对比:大修vs免拆vsDCCS——从1.8万大修到880元无效退款,三种方案该怎么选? - 趣闻早乐评
  • OpenAI 重置额度背后的技术突围:从 Codex 到上下文压缩的工程实践
  • 嵌入式开发必备:从SSCOM到协议分析,串口调试工具全解析与实战技巧
  • CAN通讯矩阵中Intel与Motorola格式解析:信号布局核心差异与实战避坑指南
  • 抓紧啦,AI软件还可以这么操作?
  • 企业AI顾问实战指南:从原理到落地的全流程解析
  • 终极指南:如何在macOS上使用IINA打造专业级视频播放体验
  • 电子工程师必备:电容选型实战指南与高频特性深度解析
  • 2026年8月广州漏水处理/广州漏水抢修工程公司帮我推荐几家_广州执盾建筑防水工程有限公司 - 行业平台推荐