您的位置:首页 > Web前端 > JavaScript

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

2019-03-18 00:01 218 查看
版权声明:转载前请联系作者,QQ:1163585385,WeChat:wangjiaqi0112,添加时声明CSDN https://blog.csdn.net/qq_26377547/article/details/88630354

老规矩,题目链接:https://leetcode-cn.com/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的情况
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: