给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
题解:使用回溯方法,每次调用DFS都传入当前的子字符串,字符串在递归调用DFS的过程中越来越长,在字符串长度等于digit长度时,将字符串压入vec,并return;
针对digits的每一位,都需要按照 数字—>字母的顺序进行遍历。
技巧:
1)可以建立map,也可以用string的方式建立;
2) DFS 处理时,可以在函数内部处理当前的位,也可以处理下一个字符对应的位,这将影响到第一次调用DFS,是循环调用,还是调用一次;
3)这个题也可以用队列的方式解决,还是比较简单点的,类似于BFS。
// Other's Code
class Solution {
public:
vector<string> letterCombinations(string digits) {
vector<string> m = {
"",
"", "abc","def",
"ghi","jkl","mno",
"pqrs","tuv","wxyz"
};
vector<string> res;
if (digits.size() == 0) return res;
string s;
DFS(digits, 0, s, res,m);
return res;
}
void DFS(string digits, int pos, string & s, vector<string> &res, vector<string>& m){
if (pos == digits.size()){
res.push_back(s);
return ;
}
//获取对应键盘的字母
string tmp = m[digits[pos] - '0'];
for (int i = 0; i < tmp.size(); i++){
s.push_back(tmp[i]);
DFS(digits, pos+1, s, res, m);
s.pop_back();
}
return ;
}
};
// my code
class Solution {
public:
vector<string> letterCombinations(string digits) {
vector<string> vec;
if (digits.size()==0) return vec;
for (int i=0;i<digits.size();i++){
if (digits[i]=='1') return vec;
}
map <char,vector<char>> phone_map;
build_map(phone_map);
for (int i=0;i<phone_map[digits[0]].size();i++){
string str;
DFS(phone_map,digits,vec,str.append(1,phone_map[digits[0]][i]));
}
return vec;
}
void DFS(map <char,vector<char>> &phone_map, string &digits,vector<string> &vec,string sub_str){
if(sub_str.size()==digits.size()){
vec.push_back(sub_str);
return;
}
for(int i=0;i<phone_map[digits[sub_str.size()]].size();i++){
string cur_str = sub_str;
cur_str.append(1,phone_map[digits[sub_str.size()]][i]);
DFS(phone_map,digits,vec,cur_str);
}
return;
}
void build_map(map <char,vector<char>> &phone_map){
char alpha = 'a';
for (char num='2';num<='9';num++){
int cycle_num =0;
if(num!='7'&&num!='9') cycle_num=3;
else cycle_num = 4;
for(int i=0;i<cycle_num;i++){
phone_map[num].push_back(alpha);
alpha++;
}
}
}
};