Bootstrap

【忍者算法】字母组合“杀手锏“:5分钟攻克电话号码的字母组合|LeetCode 17

字母组合"杀手锏":5分钟攻克电话号码的排列组合

👉 今天带你轻松掌握 LeetCode 17 题「电话号码的字母组合」

大家好,我是忍者算法。今天要聊的这道题,是面试中的经典题目,它不仅考察了递归回溯的思维,更是字符串处理的典型案例。来看看如何优雅地解决它!

🤔 从生活场景说起

还记得诺基亚手机的九宫格键盘吗?

  • 按键2对应"abc"
  • 按键3对应"def"
  • 按键4对应"ghi"

当我们要输入"hello"时,需要按:44-33-555-555-666

这个场景,其实就是今天算法题的反向操作!

💡 题目剖析

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

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

关键点在于:

  1. 每个数字对应多个字母
  2. 需要找出所有可能的组合

就像在九宫格键盘上:

  • 按下"2",可能是"a"、“b"或"c”
  • 按下"3",可能是"d"、“e"或"f”

😅 新手常见误区

很多人一开始会想:用多层循环搞定!

// ❌ 错误示范
for(char c1 : getChars(digits.charAt(0))) {
    for(char c2 : getChars(digits.charAt(1))) {
        result.add("" + c1 + c2);
    }
}

这样做的问题:

  • 代码死板:输入长度不固定怎么办?
  • 扩展性差:如果需求变化就要改很多代码

🚀 递归回溯:优雅的解法

来看看高手是怎么做的:

class Solution {
    // 建立数字到字母的映射
    private String[] letterMap = {
        "",     // 0
        "",     // 1
        "abc",  // 2
        "def",  // 3
        "ghi",  // 4
        "jkl",  // 5
        "mno",  // 6
        "pqrs", // 7
        "tuv",  // 8
        "wxyz"  // 9
    };
    
    public List<String> letterCombinations(String digits) {
        List<String> res = new ArrayList<>();
        if(digits == null || digits.length() == 0) 
            return res;
            
        backtrack(res, digits, 0, new StringBuilder());
        return res;
    }
    
    private void backtrack(List<String> res, String digits, int index, StringBuilder path) {
        // 到达叶子节点,收集结果
        if(index == digits.length()) {
            res.add(path.toString());
            return;
        }
        
        // 当前数字对应的所有可能字母
        String letters = letterMap[digits.charAt(index) - '0'];
        for(char letter : letters.toCharArray()) {
            path.append(letter);
            backtrack(res, digits, index + 1, path);
            path.deleteCharAt(path.length() - 1);
        }
    }
}

这就像:

  1. 拿起手机,准备输入
  2. 每按一个数字,就有多个字母可选
  3. 选择一个字母,继续下一个数字
  4. 直到输入完所有数字,就得到一种组合

🎯 面试常见追问

  1. 为什么用递归回溯?

    • 问题具有"选择"的特征
    • 需要尝试所有可能性
    • 符合"树形结构"的思维模型
  2. 时间复杂度是多少?

    • O(3^N × 4^M)
    • N是对应三个字母的数字个数
    • M是对应四个字母的数字个数(比如7和9)
  3. 如何优化内存使用?

    • 使用StringBuilder代替String
    • 复用路径变量而不是创建新的

📚 解题技巧总结

记住这个"回溯三部曲":

  1. 选择:append当前字母
  2. 探索:递归处理下一个数字
  3. 撤销:删除当前字母

作者:忍者算法
公众号:忍者算法

🎁 回复【刷题清单】获取LeetCode高频面试题合集
🧑‍💻 回复【代码】获取多语言完整题解
💡 回复【加群】加入算法交流群,一起进步

#算法面试 #LeetCode #回溯算法 #编程进阶

;