「算法」LeetCode 17. 电话号码的字母组合(JavaScript版)

时间:2025-04-19 07:23:50

老规矩,题目链接:/problems/letter-combinations-of-a-phone-number/
这道题的解法至少有两种,但由于本人才疏学浅,只弄懂了一种(留坑,学成后填上),如果别的小伙伴还有更好的解决办法或是觉得我的方法不正确,欢迎大家在评论区提出来~

解法1:

export default (str) => {
    // 建立电话号码键盘映射
    let map = ['', 1, 'abc', 'def', 'ghi', 'jkl', 'mno', 'pqrs', 'tuv', 'wxyz'];
    // 将输入的字符串分割成单个字符,如 123 => [2, 3, 4]
    let num = str.split('');
    // 保存键盘映射后的内容,如 23 => ['abc', 'def']
    let code = [];
    // 遍历数组num,不为空则保存到code中
    num.forEach((item) => {
        if (map[item]) {
            code.push(map[item]);
        }
    });
    // 判断边界条件
    if (!str) {
    	// 为空返回空数组
        return [];
    } else if (str.length === 1) {
    	// 只有一项时返回该项拆分后得到的数组
        return code[0].split('');
    } else {
    	// 注意使用var而不是let,避开块级作用域问题
        var comb = (arr) => {
            // 用于保存前两个组合结果的临时变量
            let tmp = [];
            for (let i = 0; i < arr[0].length; i++) {
                for (let j = 0; j < arr[1].length; j++) {
                	// 将组合后的字符串保存到tmp中
                    tmp.push(`${arr[0][i]}${arr[1][j]}`);
                }
            }
            // 前两项已经被合并成了tmp中的元素,删除前两项并替换成tmp中的元素
            arr.splice(0, 2, tmp);
            if (arr.length > 1) {
                comb(arr);
            } else {
                return tmp;
            }
            return arr[0];
        };
    }
    // 最后调用comb方法,若声明comb方法时使用了let,此处报错
    return comb(code);
}

解法1的思路如下:
首先建立电话号码键盘的映射数组map,将输入的按键数字字符串分割成单个数字保存到数组num中,对数组num进行遍历,得到对应的映射关系并保存到数组code中。接下来就采用递归的方式对数组code进行处理,将数组code中的每一个元素的每一个字母使用for循环两两组合,组合完成后保存在临时数组tmp中,由于从头开始组合,因此两两组合完成后采用splice方法,将前两项删除,替换为组合完成后得到的临时数组tmp,当数组code中的元素只剩下一个的时候,停止递归,返回临时数组tmp,然后返回数组code的第一项,即为临时数组tmp,最后调用comb方法,即为题解。

解法2:
DFS(待更填坑)

其他解法:
等等……

小结:
这道题要求理清数字与字母的映射关系,建立好映射关系后,题目就解出了一大半。采用了分治法的思想,当传入的数字只有两个时,能够很容易解决,以此类推,采用两两组合的方式可以很轻易地解出当传入的数字为三个、四个、五个、n个时的结果。这个题目涉及到了一个ES6中块级作用域的知识点。

解题笔记:

  1. 理清题意,建立数字与字母的映射关系
  2. forEach方法可以办理数组中的每一项
  3. splice方法可以将数组中的元素删除或新增,第一个参数为删除的起始点,第二个参数为需要删除的元素个数,第三个参数可选,为需要新增的数组元素
  4. 注意边界条件,即当输入为空或输入仅有一项时的边界条件
  5. 注意let和var的区别,let存在块级作用域的问题,在此题中的comb函数定义时使用let会导致最后return时comb出现undefined的情况