【LeetCode-17】电话号码的字母组合


🎉 关注“青柠代码录公众号,🔥更多精彩内容持续更新中🔥,快来加入我们吧!🚀 


 目录

🌟 问题解析与背景

核心要点:

🧩 解题思路

1. 构建数字到字母的映射表

2. 回溯法生成所有组合

3. 特殊情况处理

💻 Java 代码实现

🔍 案例执行过程分析

示例 1:输入 "23"

示例 2:输入 ""

示例 3:输入 "2" 


今天我们将探讨一个经典的回溯算法问题——电话号码的字母组合。通过详细的解题思路、完整的 Java 代码实现以及案例执行过程分析,我们将一步步揭开这个问题的奥秘。


🌟 问题解析与背景

在现代通讯工具中,电话按键上的数字与字母映射关系是一个经典的设计。

例如,按下数字键 2 对应字母 a, b, c,而按下 3 则对应 d, e, f

基于这种映射关系,给定一个仅包含数字 2-9 的字符串(即电话号码),我们需要返回所有可能的字母组合。

核心要点:

输入限制

  • 输入字符串长度范围为 [0, 4]

  • 字符串中的每个字符都属于范围 ['2', '9']

  • 数字 1 不对应任何字母。

输出要求

  • 返回所有可能的字母组合,顺序不限。

难点分析

  • 需要处理多个数字组合时的笛卡尔积问题。

  • 使用回溯算法高效生成所有组合。


🧩 解题思路

1. 构建数字到字母的映射表

首先,我们需要构建一个哈希表(或数组)来存储每个数字对应的字母集合。这是解决问题的基础数据结构。

private static final String[] KEYS = {
    "",     // 0
    "",     // 1
    "abc",  // 2
    "def",  // 3
    "ghi",  // 4
    "jkl",  // 5
    "mno",  // 6
    "pqrs", // 7
    "tuv",  // 8
    "wxyz"  // 9
};

2. 回溯法生成所有组合

回溯算法是一种递归方法,适用于解决组合问题。具体步骤如下:

终止条件

  • 如果当前索引超出了输入字符串的长度,则说明完成了一个组合,将其加入结果集。

递归逻辑

  • 获取当前数字对应的字母集合。

  • 遍历该集合中的每个字母,并将其追加到当前组合中。

  • 递归处理下一个数字。

3. 特殊情况处理

  • 如果输入为空字符串,则直接返回空列表。


💻 Java 代码实现

以下是完整的 Java 实现代码,包含了详细注释以便于理解:

import java.util.ArrayList;
import java.util.List;
​
public class Solution {
​
    // 数字到字母的映射表
    private static final String[] KEYS = {
        "",     // 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> result = new ArrayList<>();
        
        // 处理特殊情况:输入为空字符串
        if (digits == null || digits.length() == 0) {
            return result;
        }
​
        // 调用回溯函数
        backtrack(digits, 0, new StringBuilder(), result);
        return result;
    }
​
    /**
     * 回溯函数
     * @param digits 输入的数字字符串
     * @param index 当前处理的数字索引
     * @param current 当前的字母组合
     * @param result 存储所有结果的列表
     */
    private void backtrack(String digits, int index, StringBuilder current, List<String> result) {
        // 终止条件:当索引达到字符串末尾
        if (index == digits.length()) {
            result.add(current.toString());
            return;
        }
​
        // 获取当前数字对应的字母集合
        char digit = digits.charAt(index);
        String letters = KEYS[digit - '0'];
​
        // 遍历字母集合
        for (char letter : letters.toCharArray()) {
            // 添加当前字母
            current.append(letter);
​
            // 递归处理下一个数字
            backtrack(digits, index + 1, current, result);
​
            // 回溯:移除最后一个字母
            current.deleteCharAt(current.length() - 1);
        }
    }
​
    public static void main(String[] args) {
        Solution solution = new Solution();
​
        // 测试用例 1
        String digits1 = "23";
        System.out.println("输入: " + digits1);
        System.out.println("输出: " + solution.letterCombinations(digits1));
​
        // 测试用例 2
        String digits2 = "";
        System.out.println("\n输入: " + digits2);
        System.out.println("输出: " + solution.letterCombinations(digits2));
​
        // 测试用例 3
        String digits3 = "2";
        System.out.println("\n输入: " + digits3);
        System.out.println("输出: " + solution.letterCombinations(digits3));
    }
}

🔍 案例执行过程分析

示例 1:输入 "23"

执行过程:

初始状态

  • 输入字符串:"23"

  • 当前组合:空字符串 ""

  • 结果列表:空列表 []

第一步:处理数字 2

  • 数字 2 对应字母集合:"abc"

  • 遍历字母集合,依次尝试添加 a, b, c

  • 当前组合变为:"a", "b", "c"

第二步:处理数字 3

  • 数字 3 对应字母集合:"def"

  • 在每个当前组合的基础上,继续追加 d, e, f

  • "a""ad", "ae", "af"

  • "b""bd", "be", "bf"

  • "c""cd", "ce", "cf"

最终结果

  • 所有可能的组合:["ad","ae","af","bd","be","bf","cd","ce","cf"]


示例 2:输入 ""

执行过程:

  • 输入为空字符串,直接返回空列表 []


示例 3:输入 "2"

执行过程:

初始状态

  • 输入字符串:"2"

  • 当前组合:空字符串 ""

  • 结果列表:空列表 []

第一步:处理数字 2

  • 数字 2 对应字母集合:"abc"

  • 遍历字母集合,依次添加 a, b, c

最终结果

  • 所有可能的组合:["a","b","c"] 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

青柠代码录

您的鼓励是我最大的动力 '◡'

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值