题目描述:
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按任意顺序返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
思路:
从示例上来说,输入"23",最直接的想法就是两层for循环遍历,正好把组合的情况都输出了。
如果输入"233"呢,那么就三层for循环,如果"2333"呢,就四层for循环.......
理解本题后,要解决如下三个问题:
- 数字和字母如何映射
- 两个字母就两个for循环,三个字符就三个for循环,以此类推,然后发现代码根本写不出来
- 输入1 * #按键等等异常情况
代码:
class Solution {
//先将数字对应字符串存入数组(直接定义成成员变量即可)
string arr[10] = {"", "", "abc", "def", "ghi", "jkl", "mno", "pqrs", "tuv", "wxyz"};
public:
//digists数字字符串的长度就是递归的深度,每个数字所对应的字符串str的长度代表递归的广度,i标志着当前层数即递归深度
//combinStr是一种字母组合,retSV返回字符组合数组
void _letterCombinations(string& digits, size_t i, string combinStr, vector<string>& retSV)
{
//i等于数字字符串长度时,表示当前递归结束
if (i == digits.size())
{
//此时一种字母组合已经形成,将其插入返回数组中
retSV.push_back(combinStr);
return;
}
//取出当前数字(当前层)对应的字符串"abc", "def", "jkl" 等
string str = arr[digits[i] - '0'];
//循环控制宽度,递归控制深度
//j用于遍历所在层字符串的字符
for (size_t j = 0; j < str.size(); ++j)
{
//i控制递归遍历的深度,也就是层数
_letterCombinations(digits, i + 1, combinStr + str[j], retSV);
/*
combinStr+str[j] 将当前层遍历到的单个字母插入字符串,i+1 将递归深度+1进入下一层,即访问下一个数字的字符串
combinStr不可使用+=,回溯到同一层时,combStr传值调用,combStr不可被改变,因为combStr还要和其他字母组合
i也不可以使用++,因为递归之后要回溯到上一层,有循环存在,还要在进行下一路的递归,此时必须保证i还是这一层的i
插一个字母进入下一层,直到最后一层结束再向上回溯,conbinStr也就插入了不同层字母,得到多个数字字母组合
*/
}
}
vector<string> letterCombinations(string digits) {
string combinStr; //组合字符串
vector<string> retSV; //收集字符组合的返回值数组
if (digits.empty())
{
return retSV;
}
_letterCombinations(digits, 0, combinStr, retSV); //调用递归子函数
return retSV;
}
};