Offer 驾到,掘友接招!我正在参与2022春招系列活动-刷题打卡任务,点击查看活动详情。
前言
每天一道算法题,死磕算法
题目
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入: digits = "23"
输出: ["ad","ae","af","bd","be","bf","cd","ce","cf"]
分析
看到这道题我们应该立马想到这是一道排列组合的题目
排列组合题目我们应该第一时间想到回溯算法,这一定要建立起条件反射,不明白为什么排列组合要第一时间想到回溯算法的同学,可以看我的另一篇文章js算法题解(第二十天)---leetcode-46. 全排列
遇到这种问题,我们都有模板的,在复习一下就可以啦
先搞懂三个概念
- 路径(track):也就是当前已经做出的选择
- 选择列表(nums):也就是当前可以做的选择
- 结束条件: 也就是结束选择需要判断的条件
result = [];
let backTrack = function(nums,track){
if(满足条件){
result.push(track);
return;
}
for(选择 in nums){
添加到路径中
backTrack(nums,track)
从路径中撤销
}
}
所以我们就想办发让我们的题目套用我们的模板
/**
*
* @param {string} track 当前路径,因为路径都是字符串,所以track应该是字符串类型
* @param {string} nums 可选择列表,可选择列表也就是题目给出的数字,所以也是字符串
* @param {number} deep 当前深度,也就是当前选择到选择列表的第几个了
*/
var backTrack = function(track,nums,deep){
// 判断结束条件
if(track.length===nums.length){
result.push(track);
return;
}
// 解析可选择列表
let chart = nums[deep];
let words = digitsToWord[chart];
for(let i=0;i<words.length;i++){
// 添加到路径中
track+=words[i];
backTrack(track,nums,deep+1);
// 回溯,删除最后一个字符
track=track.substring(0,track.length-1);
}
}
题解
// 要返回得结果
let result = [];
// 首先定义一个号码对应字母的映射对象
const digitsToWord = {
2:'abc',
3:'def',
4:'ghi',
5:'jkl',
6:'mno',
7:'pqrs',
8:'tuv',
9:'wxyz',
}
var letterCombinations = function(digits) {
// 判断字符串是否为空
if(!digits){
return result;
}
// 要弄清路径和可选择列表
backTrack('',digits,0)
return result;
};
/**
*
* @param {*} track 当前路径
* @param {*} nums 可选择列表
* @param {*} deep 当前深度
*/
var backTrack = function(track,nums,deep){
// 判断结束条件
if(track.length===nums.length){
result.push(track);
return;
}
// 解析可选择列表
let chart = nums[deep];
let words = digitsToWord[chart];
for(let i=0;i<words.length;i++){
track+=words[i];
backTrack(track,nums,deep+1);
track=track.substring(0,track.length-1);
}
}
但是你会发现这样写在leetcode是不能通过的,因为
力扣的判题机在读取您的代码后,对每个测试用例,都会初始化一次类,但全局变量和类内静态变量需要您手动初始化。
所以我们的题解中应该避免出现全局变量和静态变量
所以符合leetcode上的答案是
var letterCombinations = function(digits) {
// 要返回得结果
let result = [];
// 判断字符串是否为空
if(!digits){
return result;
}
// 要弄清路径和可选择列表
backTrack('',digits,0,result)
return result;
};
/**
*
* @param {*} track 当前路径
* @param {*} nums 可选择列表
* @param {*} deep 当前深度
*/
var backTrack = function(track,nums,deep,result){
// 首先定义一个号码对应字母的映射对象
const digitsToWord = {
2:'abc',
3:'def',
4:'ghi',
5:'jkl',
6:'mno',
7:'pqrs',
8:'tuv',
9:'wxyz',
}
// 判断结束条件
if(track.length===nums.length){
result.push(track);
return;
}
// 解析可选择列表
let chart = nums[deep];
let words = digitsToWord[chart];
for(let i=0;i<words.length;i++){
track+=words[i];
backTrack(track,nums,deep+1,result);
track=track.substring(0,track.length-1);
}
}
总结
模板大法好,遇到了难题后,要多总结模板
遇到题型,先辨别属于哪一类题目,然后再套用模板,效率会快很多