一起刷LeetCode——电话号码的字母组合(回溯)

158 阅读2分钟

携手创作,共同成长!这是我参与「掘金日新计划 · 8 月更文挑战」的第21天,点击查看活动详情

电话号码的字母组合

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

给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。2对应abc,3对应def,4对应ghi,5对应jkl,6对应mno,7对应pqrs,8对应tuv,9对应wxyz

来源:力扣(LeetCode) 链接:leetcode.cn/problems/le…

分析

回溯

  • 使用对象存储数字对应的字母,结果是字符串数组,在获得字符串的时候,遍历电话号码的每一位,从对象中获取当前数字对应的所有字母,并且把其中的一个字母插入到当前字符串后面,然后继续处理号码的后一位,以此类推,直到遍历完所有的电话号码,得到一个完整的字符串之后,再回退到上一个分支状态,得到另一个字符串
代码(回溯)
var letterCombinations = function(digits) {
    if(!digits) return []
    const alpha = {
        2: "abc",
        3: "def",
        4: "ghi",
        5: "jkl",
        6: "mno",
        7: "pqrs",
        8: "tuv",
        9: "wxyz"
    }
    const dfs =(i,digits,temp)=>{
        if(i === digits.length){
            res.push(temp.join(''))
            return
        }
        let chars = alpha[digits[i]]
        for(let ele of chars) {
            temp.push(ele)
            dfs(i+1, digits, temp)
            temp.pop()
        }
    }
    dfs(0,digits,[])
    return res
}

BFS

  • 本题比较简单的点在于一般的回溯算法中,在得到结果的时候需要对答案进行判断是否是符合要求的结果,如果不符合的需要舍弃,本题中不会出现不符合结果的字符串,所以直接穷举所有的解就可以得到答案
代码(BFS)
const letterCombinations = (digits) => {
    if (!digits) return [];
    const map = new Map([
        ['2', ['a', 'b', 'c']],
        ['3', ['d', 'e', 'f']],
        ['4', ['g', 'h', 'i']],
        ['5', ['j', 'k', 'l']],
        ['6', ['m', 'n', 'o']],
        ['7', ['p', 'q', 'r', 's']],
        ['8', ['t', 'u', 'v']],
        ['9', ['w', 'x', 'y', 'z']],
    ]);
    const ans = map.get(digits[0]).slice();
    for (let i = 1; i < digits.length; ++i) {
        for (let j = ans.length - 1; j > -1; --j) {
            const str = ans.shift();
            map.get(digits[i]).map(char => ans.push(str + char));
        }
    }
    return ans;
};

总结

  • 本题难度等级为中等,因为得到的字符串没有非法值,所以不是很典型的回溯,但是因为对回溯算法趁热打铁,还是写了这道题
  • 写这道题的时候在想这个可能就是九宫格输入法背后的部分算法,根据按的数字推算出可能得字符串组合,然后对字符串进行拼音的识别,早期的时候,可能是一比一的识别,之后在识别这些字符组合成的字符串的时候,就更加智能,从而提升了打字速度
  • 今天也是有收获的一天