力扣-电话号码组合

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

问题分析

给定一个仅包含数字 2-9 的字符串,我们需要生成所有可能的字母组合,其中每个数字映射到一组字母(类似于电话按键)。例如:

  • 数字 "2" 映射到字母 "a", "b", "c"
  • 数字 "3" 映射到字母 "d", "e", "f"
  • 以此类推(数字 1 忽略,因为它不对应任何字母)。

这是一个组合生成问题,我们需要为输入字符串中的每个数字位置选择对应的字母,并生成所有可能的序列。例如,输入 "23",可能的组合有 "ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"。

算法思路

为了解决这个问题,我们可以使用回溯算法(backtracking)。回溯是一种通过递归探索所有可能路径的方法,并在达到终点时记录结果。思路如下:

  1. 映射定义:首先,定义一个数字到字母的映射表(例如,使用数组或映射表存储每个数字对应的字符串)。
  2. 递归回溯 :从输入字符串的第一个字符开始,对于每个数字:
    • 获取该数字对应的所有字母。
    • 遍历每个字母,将其添加到当前组合中。
    • 递归处理下一个数字位置。
    • 当处理完所有数字时,将当前组合添加到结果列表。
    • 回溯:在递归返回后,移除最后添加的字母,以便尝试其他字母。
  3. 基准情况:当所有数字处理完毕时(当前索引等于字符串长度),保存当前组合。
  4. 结果返回:递归结束后,返回所有生成的组合列表。

这种方法的时间复杂度为 O(3ᴺ × 4ᴹ) ,其中 N 是映射到 3 个字母的数字个数,M 是映射到 4 个字母的数字个数(例如数字 7 和 9)。空间复杂度为 O() L是组合长度,主要用于递归栈和结果存储。

实现过程

我们将使用 Java 实现上述思路。步骤如下:

  1. 定义映射表 :使用一个字符串数组 mapping,索引对应数字字符(例如,索引 2 存储 "abc")。
  2. 主方法 :letterCombinations 方法接受输入字符串 digits。如果输入为空或 null,直接返回空列表。
  3. 回溯方法 :定义一个递归方法 backtrack,参数包括:
    • currentCombination:当前构建的组合(使用 StringBuilder 以高效修改)。
    • index:当前处理的数字在输入字符串中的索引。
    • digits:输入字符串。
    • mapping:映射表。
    • result:存储结果的列表。
  4. 递归逻辑 :
    • 基准情况:如果 index 等于 digits.length(),说明所有数字处理完毕,将当前组合添加到 result。
    • 否则,获取当前数字对应的字母字符串。
    • 遍历每个字母:
      • 将字母添加到 currentCombination。
      • 递归调用 backtrack 处理下一个索引(index + 1)。
      • 回溯:移除 currentCombination 的最后一个字母,以便尝试下一个字母。
  5. 结果返回:初始化结果列表,调用回溯方法,返回结果。

下面是完整的 Java 实现代码:

java 复制代码
import java.util.ArrayList;
import java.util.List;

class Solution {  // 必须使用 Solution 类名
    public List<String> letterCombinations(String digits) {
        // 如果输入为空,返回空列表
        if (digits == null || digits.isEmpty()) {
            return new ArrayList<>();
        }
        
        // 定义数字到字母的映射表:索引对应数字字符('2' 到 '9')
        String[] mapping = {
            "",     // 索引 0
            "",     // 索引 1(数字 1 无映射)
            "abc",  // 索引 2(数字 2)
            "def",  // 索引 3(数字 3)
            "ghi",  // 索引 4(数字 4)
            "jkl",  // 索引 5(数字 5)
            "mno",  // 索引 6(数字 6)
            "pqrs", // 索引 7(数字 7)
            "tuv",  // 索引 8(数字 8) ← 修正这里!
            "wxyz"  // 索引 9(数字 9)
        };
        
        // 存储结果的列表
        List<String> result = new ArrayList<>();
        // 使用 StringBuilder 构建组合
        StringBuilder currentCombination = new StringBuilder();
        // 从索引 0 开始回溯
        backtrack(currentCombination, 0, digits, mapping, result);
        return result;
    }
    
    private void backtrack(StringBuilder currentCombination, int index, 
                           String digits, String[] mapping, List<String> result) {
        // 基准情况:所有数字处理完毕
        if (index == digits.length()) {
            result.add(currentCombination.toString());
            return;
        }
        
        // 获取当前数字对应的字母
        char digit = digits.charAt(index);
        String letters = mapping[digit - '0'];
        
        // 遍历当前数字对应的每个字母
        for (char letter : letters.toCharArray()) {
            currentCombination.append(letter);  // 添加字母
            backtrack(currentCombination, index + 1, digits, mapping, result);
            currentCombination.deleteCharAt(currentCombination.length() - 1);  // 回溯
        }
    }
}

代码解释

  • 映射表 :mapping 数组存储了数字 0-9 的字母映射,其中索引 0 和 1 为空(因为数字 1 无映射)。
  • 回溯方法 :backtrack 使用递归生成组合。StringBuilder 用于高效构建和修改字符串。
  • 回溯关键 :在遍历字母后,调用递归前添加字母,递归后移除字母(deleteCharAt),这确保了在尝试其他路径时组合状态正确。
  • 效率:这种方法避免了重复计算,递归深度等于输入字符串长度,适合小规模输入(LeetCode 测试用例通常较小)。

您可以调用 letterCombinations 方法测试不同输入,例如:

  • 输入 "23" 返回 "ad","ae","af","bd","be","bf","cd","ce","cf"
  • 输入 "" 返回空列表。

这个实现符合问题要求,并高效地生成了所有字母组合。

相关推荐
zyl76544 分钟前
FlashAttention 详解:从 GPU 硬件、普通 Attention 到分块计算与 Online Softmax
算法
smallyoung1 小时前
告别N+1:Spring Boot 一键数据翻译框架体系
java·后端·架构
Bazingga3 小时前
Java16 record 完整拆解——语法、语义、限制、反射
java·后端
SL_staff4 小时前
规则联动:给工厂装上‘自动化神经反射弧’——JVS·物联网平台规则引擎实战教程
java·人工智能·物联网
骑着蜗牛撵大象3274 小时前
Linux 进程间通信之管道:从 pipe() 的内核语义到 FIFO 落地排错
android·java·linux·系统编程·fifo·管道·进程间通信
爱读书的小胖5 小时前
LeetCode 122:买卖股票的最佳时机 II(C)解题分析
算法
结局无敌5 小时前
React Native for OpenHarmony 实战:三方库 react-native-modal-dialog 的鸿蒙化适配指南
深度学习·算法·react native·react.js·harmonyos
WJ.Polar5 小时前
Java封装、继承、多态
java·开发语言
ly76895 小时前
PostgreSQL 备份恢复策略:pg_basebackup、WAL 归档与 PITR 在企业 Java 系统中的落地
java·数据库·postgresql·pitr·pg_basebackup·wal 归档
摇滚侠5 小时前
Java 中如何表示负数,有符号和无符号的区别,补码的计算规则,char byte short int long 的范围
java·开发语言