每日算法 -【Swift 算法】电话号码字母组合

🚀 LeetCode 字符串数字映射(Swift)------电话号码字母组合

在日常刷题或面试中,我们经常会遇到字符串 + 回溯 组合的问题。这道经典题------电话号码的字母组合 就是典型代表。本文将带你用 Swift 实现这道题,思路清晰,代码可复用,适合初学者和进阶者。


📌 题目描述

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

每个数字映射到一些字母,和电话按键类似:

复制代码
2 → abc  
3 → def  
4 → ghi  
5 → jkl  
6 → mno  
7 → pqrs  
8 → tuv  
9 → wxyz

🧨 注意:

  • 数字 10 不对应任何字母,应直接丢弃忽略
  • 返回所有可能的组合,顺序不限

🧠 解题思路

  1. 使用 回溯算法(Backtracking)构造所有组合路径。
  2. 构造一个 数字到字母的映射字典
  3. 从第一个数字开始递归,每次递归选择当前数字对应的所有字母之一,继续向下拼接。
  4. 一旦组合的长度等于有效数字长度(不含 0 和 1),就加入结果集。

🧑‍💻 Swift 实现

swift 复制代码
class Solution {
    func letterCombinations(_ digits: String) -> [String] {
        // 数字到字母的映射表(电话按键)
        let phoneMap: [Character: String] = [
            "2": "abc", "3": "def", "4": "ghi",
            "5": "jkl", "6": "mno", "7": "pqrs",
            "8": "tuv", "9": "wxyz"
        ]

        // 过滤掉无效字符(只保留2~9)
        let filteredDigits = digits.filter { phoneMap.keys.contains($0) }
        guard !filteredDigits.isEmpty else {
            return [] // 全是0或1时,直接返回空数组
        }

        var result: [String] = []

        // 回溯函数:index表示当前处理的位置,path是当前已生成的组合
        func backtrack(_ index: Int, _ path: String) {
            // 如果已组合的长度等于有效数字长度,表示组合完成
            if index == filteredDigits.count {
                result.append(path)
                return
            }

            // 当前数字
            let digit = filteredDigits[filteredDigits.index(filteredDigits.startIndex, offsetBy: index)]
            // 对应的所有字母
            let letters = phoneMap[digit]!

            // 遍历所有字母,递归处理下一个位置
            for letter in letters {
                backtrack(index + 1, path + String(letter))
            }
        }

        // 从第0位开始回溯
        backtrack(0, "")
        return result
    }
}

🧪 测试示例

swift 复制代码
let solution = Solution()
print(solution.letterCombinations("23"))
print(solution.letterCombinations("1039"))

⏱ 时间复杂度分析

设有效输入数字长度为 n

  • 每个数字最多对应 4 个字母
  • 整体组合数量最多为 4^n

时间复杂度:

  • O(4^n * n)

空间复杂度:

  • O(n * 4^n)

✅ 总结

  • 本题是典型的 回溯 应用,适合练习组合类题目。
  • 01 的处理需特别注意。
  • 实际应用中也非常有参考价值。

🔁 拓展思考与实现

💡 1. 字典序排序

swift 复制代码
return result.sorted()

💡 2. 非递归实现

swift 复制代码
func letterCombinationsIterative(_ digits: String) -> [String] {
    let phoneMap: [Character: String] = [
        "2": "abc", "3": "def", "4": "ghi",
        "5": "jkl", "6": "mno", "7": "pqrs",
        "8": "tuv", "9": "wxyz"
    ]

    var queue: [String] = [""]

    for digit in digits {
        guard let letters = phoneMap[digit] else { continue }

        var newQueue: [String] = []
        for prefix in queue {
            for letter in letters {
                newQueue.append(prefix + String(letter))
            }
        }
        queue = newQueue
    }

    return queue.count > 1 || queue[0] != "" ? queue : []
}

💡 3. 自定义映射支持

swift 复制代码
func letterCombinations(_ digits: String, withMapping mapping: [Character: String]) -> [String] {
    let filteredDigits = digits.filter { mapping.keys.contains($0) }
    guard !filteredDigits.isEmpty else { return [] }

    var result: [String] = []

    func backtrack(_ index: Int, _ path: String) {
        if index == filteredDigits.count {
            result.append(path)
            return
        }

        let digit = filteredDigits[filteredDigits.index(filteredDigits.startIndex, offsetBy: index)]
        for letter in mapping[digit]! {
            backtrack(index + 1, path + String(letter))
        }
    }

    backtrack(0, "")
    return result
}

🏁 如果你觉得有帮助

欢迎点赞👍、收藏📂、关注我!

相关推荐
强化学习与机器人控制仿真15 小时前
RSL-RL:开源人形机器人强化学习控制研究库
开发语言·人工智能·stm32·神经网络·机器人·强化学习·模仿学习
百***480715 小时前
【Golang】slice切片
开发语言·算法·golang
q***925115 小时前
Windows上安装Go并配置环境变量(图文步骤)
开发语言·windows·golang
墨染点香16 小时前
LeetCode 刷题【172. 阶乘后的零】
算法·leetcode·职场和发展
做怪小疯子16 小时前
LeetCode 热题 100——链表——反转链表
算法·leetcode·链表
仟濹16 小时前
【Java 基础】面向对象 - 继承
java·开发语言
郝学胜-神的一滴16 小时前
Linux命名管道:创建与原理详解
linux·运维·服务器·开发语言·c++·程序人生·个人开发
2501_9416233216 小时前
C++高性能网络服务器与epoll实战分享:大规模并发连接处理与事件驱动优化经验
开发语言·php
晚风(●•σ )16 小时前
C++语言程序设计——11 C语言风格输入/输出函数
c语言·开发语言·c++
likuolei17 小时前
XML 元素 vs. 属性
xml·java·开发语言