【LeetCode】17. 电话号码的字母组合
解法思路
采用回溯算法解决字母组合问题,核心思想是递归探索所有可能的路径:
- 建立数字映射:创建数字到字母的映射关系(2-9对应标准电话键盘布局)
 - 递归回溯:逐层处理每个数字对应的字母,通过深度优先搜索构建组合
 - 路径管理:每次递归选择当前字母,完成搜索后回溯尝试其他可能
 
实现代码
func letterCombinations(digits string) []string { if len(digits) == 0 { return []string{} } // 数字到字母的映射表 phoneMap := []string{ "", // 0 "", // 1 "abc", // 2 "def", // 3 "ghi", // 4 "jkl", // 5 "mno", // 6 "pqrs", // 7 "tuv", // 8 "wxyz", // 9 } res := []string{} backtrack(&res, phoneMap, digits, 0, []byte{}) return res } func backtrack(res *[]string, phoneMap []string, digits string, index int, path []byte) { // 终止条件:完成所有数字的处理 if index == len(digits) { *res = append(*res, string(path)) return } // 获取当前数字对应的字母集合 digit := digits[index] - '0' letters := phoneMap[digit] // 遍历所有可能性 for i := 0; i < len(letters); i++ { path = append(path, letters[i]) backtrack(res, phoneMap, digits, index+1, path) path = path[:len(path)-1] // 回溯 } }
代码解析
- 
映射表设计
使用切片存储数字与字母的对应关系,索引直接对应数字值(0-9),空字符串占位无效数字 - 
递归终止条件
当处理完所有数字字符时(index == len(digits)),将当前路径转换为字符串加入结果集 - 
回溯过程
- 选择阶段:将当前字母加入路径(
path = append(...)) - 递归阶段:处理下一个数字(
index+1) - 撤销选择:移除最后添加的字母(
path = path[:len(path)-1])实现回溯 
 - 选择阶段:将当前字母加入路径(
 - 
复杂度分析
- 时间复杂度:O(3^N * 4^M)
N代表对应3字母的数字个数(2-6,8),M代表对应4字母的数字个数(7,9) - 空间复杂度:O(N)
递归栈深度最大为输入数字长度N,结果空间不计入复杂度 
 - 时间复杂度:O(3^N * 4^M)
 
测试示例验证
func main() { // 示例1:输入"23" fmt.Println(letterCombinations("23")) // 输出:[ad ae af bd be bf cd ce cf] // 示例2:输入空字符串 fmt.Println(letterCombinations("")) // 输出:[] // 示例3:输入"2" fmt.Println(letterCombinations("2")) // 输出:[a b c] }
关键优化点
- 字节切片代替字符串
使用[]byte代替字符串拼接,降低内存分配次数 - 指针传递结果集
通过指针操作结果切片,避免值传递带来的性能损耗 - 提前终止判断
主函数优先处理空输入情况,减少无效递归 
                    
                
                
            
        
浙公网安备 33010602011771号