问题描述:
题目:Leetcode 第17题
难度:中等
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。答案可以按 任意顺序 返回。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例 1:
输入:digits = "23"
输出:["ad","ae","af","bd","be","bf","cd","ce","cf"]
示例 2:
输入:digits = ""
输出:[]
示例 3:
输入:digits = "2"
输出:["a","b","c"]
提示:
0 <= digits.length <= 4
digits[i]
是范围['2', '9']
的一个数字。
BFS解法:
这道题我们可以把字母逐个排列组合的过程,看成一棵树,如图:
实际上这就很像一颗n叉树 。借用二叉树BFS的知识我们一行一行的遍历,便可以组出来。
二叉树BFS代码:
void levelorder(TreeNode tree)
{
//借用一个队列做辅助
queue<TreeNode> res;
res.push(tree);
while (!res.empty())
{
TreeNode temp = res.front();
res.pop();
//这里可以加一步,即访问temp
//遍历当前节点的左子节点和右子节点
if (temp.left != NULL)
res.push(temp.left);
if (temp.right != NULL)
res.push(temp.right);
}
}
因为最多有两个子节点所以是二叉树,如果最多有n个子节点我们可以称它为n叉树, 那么n叉树的子节点比较多,我们不可能一次性全部写完,可以使用for循环来遍历, 代码如下:
void levelorder(TreeNode root)
{
//借用一个队列做辅助
queue<TreeNode> res;
res.push(root);
while (!res.empty())
{
TreeNode temp = res.front();
res.pop();
//这里可以加一步,即访问temp
//再遍历当前节点的所有子节点
for (int i = 0;i < temp.child.count;i++)//temp.child.count表示temp子代数量
res.push(temp.child[i]);
}
}
搞懂了上面的代码,我们来看看这道题。这道题中的树是我们想象的,那我们怎么确定走到叶子节点了呢?其实如果有n个 数字,那么叶子节点字符串的长度就应该是n。
最终代码:
class Solution {
public:
vector<string> letterCombinations(string digits)
{
int n=digits.size();
vector<string> v;
queue<string> res;
res.push("");
if(n==0)
{
return v;
}
//str1储存电话键上的数字对应的所有字符串
vector<string> str1={"abc","def","ghi",
"jkl","mno","pqrs",
"tuv","wxyz"};
while(res.front().size()!=n)
{
string temp=res.front();
res.pop();
//digits.at(temp.size())-'2' 表示 digits上每个数 在电话键上对应的字符串
//其中-'2'是因为要将digits上的字符转换成对应的数同时此数还要和str1里对应字符串下标对应
//str2 就相当于 temp的子代
string str2=str1[digits.at(temp.size())-'2'];
for(int i=0;i<str2.size();i++)
{
res.push(temp+str2[i]);
}
}
int m=res.size();
for(int i=0;i<m;i++)
{
v.push_back(res.front());
res.pop();
}
return v;
}
};
DFS解法:
除了BFS自然会想到DFS,特殊的是这里往回走的时候并不需要撤销选 择,因为字符串每次都会生成一个新的对象。
具体代码:
class Solution {
public:
queue<string> res;
void DFS( string digits, string str, vector<string>& str1, int index)
{
if (str.size() == digits.size())
{
//到叶子节点了,就把这条路径选择的字符添加到res中
res.push(str);
}
else
{
string str2 = str1[digits.at(index) - '2'];
//访问当前节点的所有子节点
for (int i = 0;i < str2.size();i++)
{
DFS( digits, str + str2[i], str1, index + 1);
}
}
/**
* res
* index 表示访问到第几个数字了,也可以认为访问到树的第几层了
* digits
* tab
* path 从根节点到叶子结点的路径
*/
}
vector<string> letterCombinations(string digits)
{
int n = digits.size();
vector<string> v;
if (n == 0)
{
return v;
}
//str1储存电话键上的数字对应的所有字符串
vector<string> str1 = { "abc","def","ghi",
"jkl","mno","pqrs",
"tuv","wxyz" };
DFS( digits, "", str1, 0);
int m = res.size();
for (int i = 0;i < m;i++)
{
v.push_back(res.front());
res.pop();
}
return v;
}
};