给定一个仅包含数字 2-9
的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23" 输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = "" 输出:[]
示例 3:
输入:digits = "2" 输出:["a","b","c"]
题目链接:17. 电话号码的字母组合 - 力扣(LeetCode)
视频链接:还得用回溯算法!| LeetCode:17.电话号码的字母组合_哔哩哔哩_bilibili
这个题和之前的n个数取k个组合很像。我们依旧按照树的结构处理
审题:每个数字对应一串字符,那我们可以用二维数组或者映射来记录。这里定义一个二维数组,代码如下:
const string letterMap[10] = {
"", // 0
"", // 1
"abc", // 2
"def", // 3
"ghi", // 4
"jkl", // 5
"mno", // 6
"pqrs", // 7
"tuv", // 8
"wxyz" // 9
};
图中可以看出遍历的深度,就是输入"23"的长度,而叶子节点就是我们要收集的结果,输出["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"]。
回溯三部曲:
1、确定参数和返回值
首先需要一个字符串s来收集叶子节点的结果,然后用一个字符串数组result保存起来
参数指定是有题目中给的string digits,然后还要有一个参数就是int型的index。
注意这个index不是 77.组合 (opens new window)和216.组合总和III (opens new window)中的startIndex。因为本题不用考虑组合重复问题而设置起始位限制。这个index是记录遍历第几个数字了,就是用来遍历digits的(题目中给出数字字符串),同时index也表示树的深度。
vector result;
string s;
void backtracking(const string& digits, int index)
2、确定终止条件
例如输入用例"23",两个数字,那么根节点往下递归两层就可以了,叶子节点就是要收集的结果集。那么终止条件就是如果index 等于 输入的数字个数(digits.size())了(本来index就是用来遍历digits的)。
然后收集结果,结束本层递归。
注意小细节:index要指向3后面的位置才算结尾,因为只有遍历完3,才能从下一层递归中执行到终止判定语句。发现终止,return空然后跑路,不再继续执行了。
if (index == digits.size()) {
result.push_back(s);
return;
}
3、确定单层递归的逻辑
首先要取index指向的数字,并找到对应的字符集
然后for循环来处理这个字符集,代码如下:
int digit = digits[index] - '0'; // 将index指向的数字转为int
string letters = letterMap[digit]; // 取数字对应的字符集
for (int i = 0; i < letters.size(); i++) {
s.push_back(letters[i]); // 处理
backtracking(digits, index + 1); // 递归,注意index+1,一下层要处理下一个数字了
s.pop_back(); // 回溯
}
4代码
class Solution {
private:
const string letterMap[10] = {"","","abc","def","ghi","jkl","mno","pqrs","tuv","wxyz"};//用数组表示映射
public:
string s; //储存每一层递归中要添加的数
vector result; //储存结果
void backtracking(string digits, int index) { //index用于记录遍历到digits的第几个数字
//这里index指向digits身后一位才说明遍历完成了,注意下标问题
//因为只有进入下一次递归,才能运行这个终止判断语句
if (digits.size() == index) {
result.push_back(s);
return ;
}
int digit = digits[index] - '0';//将index指向的字符转换成int类型的数字
string letters = letterMap[digit];//取数字对应的字符集,如digit=2,letters="abc"
for (int i = 0; i < letters.size(); i++) { //i管理的是本层递归树中的遍历
s.push_back(letters[i]);//添加
backtracking(digits, index+1);//递归
s.pop_back();//回溯
}
}
vector letterCombinations(string digits) {
if (digits.size() == 0) return result;
backtracking(digits, 0);
return result;
}
};