手机数字键中字母组合 - JavaScript版

1,260 阅读1分钟

问题

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

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。

在这里插入图片描述

示例:

输入:"23" 输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]. 说明: 尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。

思路

以上面示例为例: "2" 和 "3" 对应的是["a", "b", "c"]["d", "e", "f"] 之间所有的组合情况。在所产生的结果结构如下:

树状示意图

这实际上可以看作是A = { a, b, c }B = {d, e, f}这两个集合的笛卡尔积运算, 为A × B

如果有第三个数字4,对应集合C = { g, h, i },则结果为A × B × C

所以步骤为:

  1. 列出数字对应的集合列表[ A, B, C, ...]
  2. 计算A × B × C × ...

代码

// 数字 2 - 9 对应的字母集合
const PhoneChart = [
  ['a', 'b', 'c'],
  ['d', 'e', 'f'],
  ['g', 'h', 'i'],
  ['j', 'k', 'l'],
  ['m', 'n', 'o'],
  ['p', 'q', 'r', 's'],
  ['t', 'u', 'v'],
  ['w', 'x', 'y', 'z']
]

/**
 * @param {string} digits
 * @return {string[]}
 */
var letterCombinations = function(digits) {
  // 示输入为空为空就可以提前退出了
  if(digits.length <= 0) return []

  // 获取集合列表
  const letters = digits.split('').map(index => PhoneChart[index - 2])

  let rs = letters[0]
  // 对集合列表中的项挨个进行“笛卡尔积”计算
  for(let i = 1; i < letters.length; i++) {
    rs = [].concat(...letters[i].map(addon => rs.map(pre => pre + addon)))
  }
  return rs
};