leetcode刷题记录-17. 电话号码的字母组合

194 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

前言

今天第二题难度为中等,主要是涉及到了递归的问题,我是使用了回溯算法来进行解题,当然这不是唯一解,dfs的解法应该也是能够求出这道题的答案的

每日一题

第二题的题目是 17. 电话号码的字母组合,难度为中等

  • 给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。

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

image.png  

示例 1:

输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]

示例 2:

输入:digits = ""
输出:[]

示例 3:

输入:digits = "2"
输出:["a","b","c"]

 

提示:

  • 0 <= digits.length <= 4
  • digits[i] 是范围 ['2', '9'] 的一个数字。

题解

回溯算法

关于回溯算法,解决的问题也很直观,我们看一下题目,要求用每个数字代表的字母组成所有情况,比如说两个数字 “23” 那么就是:

let num2 = 'abc'
let num3 = 'def'
let res = []
for(let i=0;i<num2.length;i++){
    for(let j=0;j<num3.length;j++){
        res.push(num2[i] + num3[j])
    }
}
return res

最后获得的这个 res 就是我们要的数组了,但是,如果当题目给出的 digits 更长呢,那么这个循环将会嵌套特比多层,那么就特别头疼了,所以这时候我们就需要用回溯算法来解决这个问题。

现在我们需要设计一个递归函数,然后我们来思考这个函数的退出条件,看到题目给的 digits 和之后的答案数组,我们不难发现,答案数组中的每一个元素,长度都是和 digits 相同的,那么我们就能够知道了,在什么时候我们会成功组合出一个答案呢,当这个答案的长度等于 digits 的时候。

那么在得出了退出条件之后,我们就需要在每一次递归的时候去加长我们的其中一个答案元素,那么这个答案元素从哪里来,很明显,我们可以用一个数组存下题目给的 2-9 这 8 个数字相对于的字符串,然后每次加长的长度就是从这些字符串里来。

那么将以上结合起来,我们需要一个临时数组,用于存放每一个答案元素,在满足退出条件的时候,也就是长度等于 digits 的时候将它加入答案数组,并且退出递归。

/**
 * @param {string} digits
 * @return {string[]}
 */
var letterCombinations = function (digits) {
  const k = digits.length;
  const map = [
    "",
    "",
    "abc",
    "def",
    "ghi",
    "jkl",
    "mno",
    "pqrs",
    "tuv",
    "wxyz",
  ];
  if (!k) return [];
  if (k === 1) return map[digits].split("");

  let res = [];
  let path = [];

  function recursion(a) {
    if (path.length === k) {
      res.push(path.join(""));
      return;
    }
    for (const v of map[digits[a]]) {
      path.push(v);
      recursion(a + 1);
      path.pop();
    }
  }

  recursion(0);
  return res;
};

image.png