给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 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']
的一个数字。
class Solution {
public:
vector<string> letterCombinations(string digits) {
vector<string> coms;
if(digits.empty()){
return coms;
}
unordered_map<char,string> phoneMap{
{'2',"abc"},
{'3',"def"},
{'4',"ghi"},
{'5',"jkl"},
{'6',"mno"},
{'7',"pqrs"},
{'8',"tuv"},
{'9',"wxyz"}
};
string com;
backtrack(coms,phoneMap,digits,0,com);
return coms;
}
void backtrack(vector<string>& coms,const unordered_map<char,string>& phoneMap,const string& digits,int index,string& com){
if(index==digits.size()){
coms.push_back(com);
}else{
char digit=digits[index];
const string& letters=phoneMap.at(digit);
for(const char& letter:letters){
com.push_back(letter);
backtrack(coms,phoneMap,digits,index+1,com);
com.pop_back();
}
}
}
};
整体来说这道题的思路是枚举,只不过用回溯法去降低时间复杂度。用哈希表存储所有数字字符对应的字母的可能性,然后遍历字符。比如给出的字符为“23”,那么我们先去找到2对应的字母为abc,找到之后先对a进行处理,递归进入的是3对应的字符“def”,但是递归这里有点难想,进入递归之后相当于进入一次嵌套循环(我是这里理解的),然后遍历def,d完成遍历后,index等于digits的长度,coms则添加第一个结果字符ad,然后此时回到上次递归状态,注意此时是第3次使用backtrack,因此我们回到第二次调用,即遍历def的时候,先释放掉com,再继续遍历e,直到遍历完成。同样的遍历完def之后,回到上一层,继续遍历a的下一个,也就是b,直到全部情况遍历完成。其实递归的作用就有点类似于嵌套循环的过程,但是这里的index没有重置,因为递归的情况下,它退回上一层状态,相当于自动重置。