给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
输入:”23”
输出:[“ad”, “ae”, “af”, “bd”, “be”, “bf”, “cd”, “ce”, “cf”].
这道题是一个典型的组合问题,组合问题可以采用回溯法解决。回溯法的介绍以及一般的解题步骤可以参考回溯法的一般解体步骤。
在这里我对上面的排列树以及程序框架之间的关系做一个进一步的解释。
/*
* output(x) 记录或输出得到的可行解x
* constraint(t) 当前结点的约束函数
* bount(t) 当前结点的限界函数
* @param t t为当前解空间的层数
* @param n 树高
*/
void backtrack(int t){
if(t >= n) output(x);
else
for (int i = t; i <= n; i++) {
swap(x[t], x[i]);
if(constraint(t) && bount(t))
backtrack(t+1);
swap(x[t], x[i]);
}
}
比如,我们要求序列1,2,3,4的全排列,那么排列树就如上面所示。回溯法采用DFS的搜索策略。比如,我们第一个位置确定为1,第二个位置确定为2,第三个位置确定为3,第四个位置确定为4,这个时候解空间的层数已经达到树的高度,此时应该回溯,因此在代码里出现了if(t >= n) output(x),这就是回溯法第一个重要的位置设置出口条件。具体的output根据题目要求,是存储到一个空间里,还是输出,因题而异。
那么给出了第一个可能解1,2,3,4之后,如何确定下一个解呢,从图中可以看到下一个解应该是1,2,4,3,那么是如何确定下一个解的呢?在程序中通过一个循环for (int i = t; i <= n; i++)达到遍历每一种情况。一共有n种取值(n层),在t层的时候已经使用了t种取值。因此,只遍历n-t+1种取值。通过swap(x[t], x[i])来替换第t+i层的取值可能,然后继续调用backtrack(t+1)完成下一层的递归。当然,当遍历完当前位置取值a的子树对应的所有可能解之后,需要遍历下一个取值b,那么就需要还原情形,即swap(x[t], x[i])。
在这个问题中,因为每一个字母对应的数字不一样,因此无法通过循环去遍历。上面的for循环,无非是用一行代码将所有的情况列出。我对于这个题的解决方式是通过if将所有的情况给出。比方说下面的代码中if当前位置是2的情况,那么它可能会对应a,b,c三种情况。当我取a的时候,继续通过调用dfs(phone,++index,store,temp)去判断其子树对应的可能解的所有情况。在这之前前,需要通过temp字符串保存当前路径构成的字母字符串,即取a的时候,将a加入字符串,当a对应的子树遍历完,那么取b之前,我们需要将temp的a删除,同时将准备判断的数字字符位置index减1,即还原到当前位置。
而出口条件是,当temp字符串长度达到了phone的数字长度,就退出递归回溯。
class Solution {
public:
vector letterCombinations(string digits) {
vector store;
if(digits.size()==0) return store;
string temp = "";
dfs(digits,0,store,temp);
return store;
}
void dfs(string phone,int index,vector &store,string temp){
if(index==phone.size()){
store.push_back(temp);
return;
}
if(phone[index]=='2'){
temp = temp + 'a';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'b';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'c';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='3'){
temp = temp + 'd';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'e';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'f';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='4'){
temp = temp + 'g';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'h';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'i';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='5'){
temp = temp + 'j';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'k';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'l';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='6'){
temp = temp + 'm';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'n';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'o';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='7'){
temp = temp + 'p';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'q';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'r';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 's';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='8'){
temp = temp + 't';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'u';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'v';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
else if(phone[index]=='9'){
temp = temp + 'w';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'x';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'y';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
temp = temp + 'z';
dfs(phone,++index,store,temp);
temp = temp.substr(0,temp.size()-1);
index--;
}
}
};