leetcode刷题记录-17. 电话号码的字母组合(回溯组合问题)

116 阅读1分钟

持续创作,加速成长!这是我参与「掘金日新计划 · 10 月更文挑战」的第28天,点击查看活动详情

前言

今天的题目为中等,主要是用于重新的学习一下回溯算法,并且按照特定的解题技巧来解决一下回溯,之后可能会专门训练一下回溯的各种题型。

每日一题

今天的题目是 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'] 的一个数字。

题解

组合回溯1 leetcode刷题记录-77. 组合(回溯基础)

组合回溯2 leetcode刷题记录-216. 组合总和 III(回溯剪枝)

回溯

同样是利用回溯的思维,但是这道题和前两天的有些不同,前两天的都是数字的组合问题,解题的方式完全一样,今天见到了另一种组合方式,多个字符串的组合,题目的根本就是就是求几个字符串自由组合,能够有几种组合的方式,我们拿最简单的 2,3 来说,那就是 abcdef 组合共有几种方式,一样的,我们可以先考虑for循环的解法,通过两次for循环,能够得到 ad ae af bd be bf cd ce cf 这9种解,但是万一这个数字的数量增多,那就只能同步增加for循环的数量,显然不合理,那么就该回溯登场。

首先要写一个回溯,我们要根据三部曲来进行,第一是考虑回溯函数的参数,这道题我们需要获取当前再题目给的字符串的哪个位置,所以需要一个参数index,然后根据这个index就能够知道现在遍历的是哪个数字,我们在维护一个map表,通过map表去找到这个数字对应的字母,然后就可以通过for循环来遍历字母进行组合

第二就是需要考虑到结束条件。结束的条件就是当当前的组合字符串长度刚好和输入的字符串长度一样,就代表当前的分支到头了。

最后就是回溯的操作,我们初始化一个空字符串,在每次加上当前字符对象的字母,然后在递归过后进行回溯,也就是删掉最后一个字符。

综上,就能够完成这道回溯题

const numMap = {
  2: 'abc',
  3: 'def',
  4: 'ghi',
  5: 'jkl',
  6: 'mno',
  7: 'pqrs',
  8: 'tuv',
  9: 'wxyz',
}
function letterCombinations(digits) {
  let res = []
  let str = ''
  if (digits.length == 0) return []
  const backtracking = (index) => {
    if (str.length == digits.length) {
      res.push(str)
    }
    if (isNaN(parseFloat(digits[index]))) return
    let n = digits[index]
    for (let i = 0; i < numMap[n].length; i++) {
      str += numMap[n][i]
      backtracking(str.length)
      str = str.slice(0, str.length - 1)
    }
  }
  backtracking(0)
  return res
};

image.png