DFS实现:数据结构:栈 BFS实现:数据结构:队列
典型示例:二叉树广度优先遍历和深度优先遍历
//广度优先遍历
void BFS(Tree root){
queue<Node *> nodeQueue;
nodeQueue.push(root);
Node *node;
while(!nodeQueue.empty()){
node = nodeQueue.front();
nodeQueue.pop();
cout<<node->data;//遍历根结点
if(node->lchild){
nodeQueue.push(node->lchild); //先将左子树入队
}
if(node->rchild){
nodeQueue.push(node->rchild); //再将右子树入队
}
}
}
//深度优先遍历
void DFS(Tree root){
stack<Node *> nodeStack;
nodeStack.push(root);
Node *node;
while(!nodeStack.empty()){
node = nodeStack.top();
cout<<node->data;//遍历根结点
nodeStack.pop();
if(node->rchild){
nodeStack.push(node->rchild); //先将右子树压栈
}
if(node->lchild){
nodeStack.push(node->lchild); //再将左子树压栈
}
}
}
典型例题:
1 广度搜索:打开转盘锁
https://leetcode-cn.com/explore/learn/card/queue-stack/217/queue-and-bfs/873/
你有一个带有四个圆形拨轮的转盘锁。每个拨轮都有10个数字: '0', '1', '2', '3', '4', '5', '6', '7', '8', '9'
。每个拨轮可以自由旋转:例如把 '9'
变为 '0'
,'0'
变为 '9'
。每次旋转都只能旋转一个拨轮的一位数字。
锁的初始数字为 '0000'
,一个代表四个拨轮的数字的字符串。
列表 deadends
包含了一组死亡数字,一旦拨轮的数字和列表里的任何一个元素相同,这个锁将会被永久锁定,无法再被旋转。
字符串 target
代表可以解锁的数字,你需要给出最小的旋转次数,如果无论如何不能解锁,返回 -1。
示例 :
输入:deadends = ["0201","0101","0102","1212","2002"], target = "0202" 输出:6 解释: 可能的移动序列为 "0000" -> "1000" -> "1100" -> "1200" -> "1201" -> "1202" -> "0202"。 注意 "0000" -> "0001" -> "0002" -> "0102" -> "0202" 这样的序列是不能解锁的, 因为当拨动到 "0102" 时这个锁就会被锁定。
class Solution {
public:
int openLock(vector<string>& deadends, string target) {
set<string>l(deadends.begin(),deadends.end());
if(l.count("0000"))
return -1;
queue<string>q;
q.push("0000");
set<string> v;
v.insert("0000");
int step = 0;
int dir[2] = {-1,1};
while(!q.empty())
{
int size = q.size();
step++;
for(int i = 0;i < size;i++)
{
string str = q.front();
q.pop();
for(int j = 0;j < 4;j++)
{
for(int t = 0;t < 2;t++)//尝试每一种情况
{
char ch = str[j];//记录保存当前值,避免缺少部分情况
str[j] = (str[j] -'0' + 10 + dir[t]) % 10 + '0';
if(str == target)
return step;
if(v.count(str) !=0 || l.count(str)!=0 )//锁里面没有且未被使用过
{
str[j] = ch;
continue;
}
v.insert(str);
q.push(str);
str[j] = ch;//修改回原来的值
}
}
}
}
return -1;
}
};
2 深度搜索:钥匙和房间
https://leetcode-cn.com/explore/learn/card/queue-stack/220/conclusion/893/
有 N
个房间,开始时你位于 0
号房间。每个房间有不同的号码:0,1,2,...,N-1
,并且房间里可能有一些钥匙能使你进入下一个房间。
在形式上,对于每个房间 i
都有一个钥匙列表 rooms[i]
,每个钥匙 rooms[i][j]
由 [0,1,...,N-1]
中的一个整数表示,其中 N = rooms.length
。 钥匙 rooms[i][j] = v
可以打开编号为 v
的房间。
最初,除 0
号房间外的其余所有房间都被锁住。
你可以自由地在房间之间来回走动。
如果能进入每个房间返回 true
,否则返回 false
。
示例 :
输入: [[1],[2],[3],[]] 输出: true 解释: 我们从 0 号房间开始,拿到钥匙 1。 之后我们去 1 号房间,拿到钥匙 2。 然后我们去 2 号房间,拿到钥匙 3。 最后我们去了 3 号房间。 由于我们能够进入每个房间,我们返回 true。
class Solution {
public:
bool canVisitAllRooms(vector<vector<int>>& rooms) {
if (rooms.empty()) {
return false;
}
stack<int> remainRoom;
unordered_set<int> visit;
visit.insert(0);
for (int i = 0; i < rooms[0].size(); i++) {
remainRoom.push(rooms[0][i]);
}
while (!remainRoom.empty()) {
int curRoom = remainRoom.top();
remainRoom.pop();
if (visit.size() == rooms.size()) {
return true;
}
if (visit.count(curRoom) == 0) {
visit.insert(curRoom);
for (int i = 0; i < rooms[curRoom].size(); i++) {
remainRoom.push(rooms[curRoom][i]);
}
}
}
if (visit.size() == rooms.size()) {
return true;
} else {
return false;
}
}
};