题目
思路
本题的难点之一是如何更好的将数字转换为相应的字母,一开始我的思路是使用hash,但是并不能很好的解决问题,如下图:
从上图中我们可以知道,我们的目的就是要找出所有到达叶节点的路径,换句话说就是当到达树的深度时,我们便回头,很明显这是回溯法类型的题目。那么分析以下本题存在的难点和相关知识点:
- 首先,相对于传统的回溯法类型的题目,本道题是一个数字代表三个或者四个字母,我们要避免选到同一组的字母
- 接着如何更好的将数字转换为相应的字母集合,如果使用哈希思想,那么怎样的哈希映射才是最方便的
- 如何回溯
其实我们看,本道题相比较传统的回溯法类型的题目,难点和重点就是数字如何映射到相应的字母集合,先看代码:
class Solution {
public:
vector<string> res;
string path;
vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
void dfs(int& depth, string digits) {
int n = digits.size();
if (depth == n) {
res.push_back(path);
return;
}
for (unsigned int i = 0; i < table[digits[depth] - '2'].size(); i++) {
path.push_back(table[digits[depth] - '2'][i]);
depth += 1;
dfs(depth, digits);
depth -= 1;
path.pop_back();
}
}
vector<string> letterCombinations(string digits) {
if (digits == "")
return res;
int depth = 0;
dfs(depth, digits);
return res;
}
};
首先我们设置一个全局的容器变量,表示数字到字母的映射:
vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
接着就是深度搜索:
void dfs(int& depth, string digits) {
int n = digits.size();
if (depth == n) {
res.push_back(path);
return;
}
for (unsigned int i = 0; i < table[digits[depth] - '2'].size(); i++) {
path.push_back(table[digits[depth] - '2'][i]);
depth += 1;
dfs(depth, digits);
depth -= 1;
path.pop_back();
}
}
首先深度搜索函数具有两个参数,遍历到的深度,还有该深度的数字所对应字母集合的size大小,我们第一步先设置递归(回溯算法基本是运用递归算法)的基准条件,那么基准条件就是到达树的叶节点,也就是达到了树的深度;
接着就到了本道题的重点和难点:如何循环。那么我们之前设置了一个全局的容器变量,这里我们巧妙地利用此时遍历到地树的深度,和该映射容器相结合,树的深度代表遍历到了第几个数字,那么我们就可以映射到相对应地字母集合,如下面定义:
table[digits[depth] - '2'].size();
我们解读一下,depth表示遍历到第几个数字,然后再将该位置地数字映射到相对应的字母集合。然后就是按照下图开始回溯:
下面介绍另外一种方法:广度优先
我们也可以这样解题:
设置一个队列,每遍历一个数字,我们就将队列中的元素逐个与该数字所对应的字母集合相结合,并再次放进队列中,如下图演示:
相关代码如下:
class Solution {
public:
//bfs
vector<string> letterCombinations(string digits) {
vector<string> res;
if (digits == "")
return res;
deque<string> d;
vector<string> table{ "abc","def","ghi","jkl","mno","pqrs","tuv","wxyz" };
int n = digits.size();
for (int i = 0; i < table[digits[0] - '2'].size(); i++) {
string str;
str.push_back(table[digits[0] - '2'][i]);
d.push_back(str);
}
for (int i = 1; i < n; i++) {
int len = d.size();
while (len--) {
for (int j = 0; j < table[digits[i] - '2'].size(); j++) {
string str = d.front();
str += table[digits[i] - '2'][j];
d.push_back(str);
}
d.pop_front();
}
}
res.assign(d.begin(),d.end());
return res;
}
};