今天 leetcode 写了一道题,它既可以用深度优先搜索,也可以用广度优先搜索来解决,不妨一起来看看吧!
题目描述
给定一个仅包含数字 2-9 的字符串,返回所有它能表示的字母组合。
给出数字到字母的映射如下(与电话按键相同)。注意 1 不对应任何字母。
示例:
输入:"23"
输出:["ad", "ae", "af", "bd", "be", "bf", "cd", "ce", "cf"].
说明:
尽管上面的答案是按字典序排列的,但是你可以任意选择答案输出的顺序。
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/letter-combinations-of-a-phone-number
下面,我们将分别使用 DFS 和 BFS 来解决该问题。
深度优先搜索(DFS)
Depth-First-Search:深度优先搜索,它沿着树的深度遍历树的节点,尽可能深的搜索树的分 支。当节点的所有边都己被访问过,搜索将回溯到原节点边的起始节点。这一过程一直进行到已发现从原节点可达的所有节点为止。如果存在未被访问的节点,则选择其中一个作为节点并重复以上过程,整个进程反复进行直到所有节点都被访问为止。
打个不恰当的比方,你开车去一个地方,但是路上分叉路多,你又没地图,那只能把每个分叉路走都走一遍,走到头也没到,返回之前路口再走,最多把所有的子路径都走一遍就能到达目的地。
下面,我们来看看如何利用 DFS 来解决这个问题。
以一个例子来看,"237"。
这是一个示意图,用画布画的,有些丑。。。
简单模拟下这个过程
先从 '2' 的一个节点 a 出发,发现还能往下走,就来到了 '3' 的一个节点 d ,发现还可以继续往下走,就来到了 '7' 的一个节点 p,这个时候再往下走就不行了,此时我们把 "adp" 存起来。
由于已经无路可走了,只能返回之前的节点,再往下走,来到 q ,再往下走,无路可走了,把 "adq" 存起来。
重复上面的过程。
那么终止条件是什么呢?当然是"层数"了
图示过程:
程序如下:
class Solution {
public:
vector res;
unordered_map store;
vector letterCombinations(string digits) {
if(digits.empty()){
return res;
}
store = {
{'2',"abc"}, {'3',"def"}, {'4',"ghi"}, {'5',"jkl"}, {'6',"mno"}, {'7',"pqrs"}, {'8',"tuv"} , {'9',"wxyz"}};
dfs("", 0,digits);
return res;
}
void dfs(string str,int index,string digits){
int len=digits.size();
if(len==index){
res.push_back(str);
return ;
}
string targerStr=store[digits[index]];
for(auto temp : targerStr){
dfs(str+temp,index+1,digits);
}
return ;
}
};
广度优先搜索(BFS)
BFS是从根节点开始,沿着树(图)的宽度遍历树(图)的节点。如果所有节点均被访问,则算法中止。
简单模拟下这个过程:
先把根节点入队列:
再找下一个未被访问的节点:
当然我们不能简单地把 "def" “塞进去”,"def" 进去后的结果应该是其与队列中所有成员的组合。
这个过程可以这样操作:
队列中所有元素都分别加上当前节点的所有元素。
之后重复这样的操作:
程序如下:
class Solution {
public:
vector res;
unordered_map store;
vector letterCombinations(string digits) {
if(digits.empty()){
return res;
}
store = {{'2',"abc"}, {'3',"def"}, {'4',"ghi"}, {'5',"jkl"}, {'6',"mno"},{'7',"pqrs"}, {'8',"tuv"}, {'9',"wxyz"}};
queue q;
q.push("");
for(auto temp : digits){
string targetStr=store[temp];
int qSize=q.size();
//位于当前层,添加字符
for(int i=0;i
这个题使用深度优先搜索(DFS)和广度优先搜索(BFS)都可以解决,下面我们汇总两个程序。
汇总
把这个两个程序汇总,更方便我们测试,整理如下:
#include
using namespace std;
class DFS_{
public:
vector res;
string digits;
unordered_map store;
vector letterCombinations(){
this->digits = digits;
if (digits.empty()){
return res;
}
store = unordered_map{{'2', "abc"}, {'3', "def"}, {'4', "ghi"}, {'5', "jkl"}, {'6', "mno"}, {'7', "pqrs"}, {'8', "tuv"}, {'9', "wxyz"}};
dfs("", 0);
return res;
}
void dfs(string resultStr, int index){
int digitsSize = this->digits.size();
if (digitsSize == index){
res.push_back(resultStr);
return ;
}
string targetStr = store[this->digits[index]];
for (auto tmpChar : targetStr){
dfs(resultStr + tmpChar, index + 1);
}
return ;
}
};
class BFS_{
public:
vector res;
string digits;
unordered_map store;
vector letterCombinations(){
this->digits = digits;
if(digits.empty()){
return res;
}
store = {{'2',"abc"}, {'3',"def"}, {'4',"ghi"}, {'5',"jkl"}, {'6',"mno"},{'7',"pqrs"}, {'8',"tuv"}, {'9',"wxyz"}};
queue q;
q.push("");
for(auto temp : digits){
string targetStr=store[temp];
int qSize=q.size();
//位于当前层,添加字符
for(int i=0;i>str;
DFS_ d;
BFS_ b;
d.digits=str;
b.digits=str;
vector res_d = d.letterCombinations();
cout<<"DFS: "< res_b = b.letterCombinations();
for(auto& temp : res_b){
cout<
示例如下:
虽然 DFS 和 BFS 的理论不难理解,实际应用过程中还是需要多加练习,才能很好地掌握。