17.Letter Combinations of a Phone Number

25 年 7 月 15 日 星期二
520 字
3 分钟

17. Letter Combinations of a Phone Number

Screenshot 2026-03-08 at 11.23.05 am

为什么电话号码字母组合的代码里不需要 onPath 数组,而全排列的代码却必须用,核心原因在于这两个问题的选择规则和元素来源完全不同

核心差异分析

先明确两个问题的选择逻辑:

  1. 电话号码字母组合(letterCombinations)

    • 每个位置(第 i 位)的选择范围是固定且独立的:只和输入数字的第 i 位对应(比如数字 2 对应 abc,数字 3 对应 def)。
    • 不同位置的选择互不干扰,且同一位置的字母不会重复选(比如第 0 位选了 a,第 1 位选 d,不存在 “重复选同一个元素” 的问题)。
    • 本质是按位置依次选取固定集合中的元素,没有 “选过 / 没选过” 的状态需要记录。
  2. 全排列(permute)

    • 所有位置的选择范围都是同一个数组 nums,但要求每个元素只能选一次(比如 nums=[1,2,3],第 0 位选了 1,后面就不能再选 1)。
    • 本质是从同一集合中选不重复的元素填充位置,必须记录 “哪些元素已经被选过”,否则会出现重复(比如 [1,1,2] 这种无效排列)。

Solution:

python
MAPPING = "", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"

class Solution:
    def letterCombinations(self, digits: str) -> List[str]:
        if not digits:
            return []
        n = len(digits)
        path = [''] * n # 注意 path 长度一开始就是 n,不是空列表
        ans = []
        def dfs(i):
            if i == n: # 不是 n-1
                ans.append(''.join(path))
                return
            for c in MAPPING[int(digits[i])]:
                path[i] = c # 直接覆盖,不用恢复现场
                dfs(i + 1)
        dfs(0)
        return ans

复杂度分析

  • 时间复杂度:O(n4^n),其中 n 为 digits 的长度。最坏情况下每次需要枚举 4 个字母,递归次数为一个满四叉树的节点个数,那么一共会递归 O(4^n) 次(等比数列和),再算上加入答案时复制 path 需要 O(n) 的时间,所以时间复杂度为 O(n4^n)。
  • 空间复杂度:O(n)。返回值的空间不计。

文章标题:17.Letter Combinations of a Phone Number

文章作者:Sirui Chen

文章链接:https://blog.siruichen.me/posts/17letter_combinations_of_a_phone_number[复制]

最后修改时间:


商业转载请联系站长获得授权,非商业转载请注明本文出处及文章链接,您可以自由地在任何媒体以任何形式复制和分发作品,也可以修改和创作,但是分发衍生作品时必须采用相同的许可协议。
本文采用CC BY-NC-SA 4.0进行许可。