目录
广度优先搜索代码框架
广度优先搜索 主要用来解决在一幅图中, 找到从起点到终点的最近距离.
主要使用队列数据结构来存储每一步所要处理的数据
使用set来记录处理的数据是否访问过
代码框架
int BFS(Node start, Node target)
{
queue<Node> q; //核心数据结构
set<Node> visited; //记录访问过的节点
q.push(start); //将起点加入队列
visited.insert(start);
int step = 0; //记录扩散的步数
while(!q.empty())
{
int sz = q.size();
//将当前队列中的所有节点向四周扩散
for(int i = 0; i<sz; i++)
{
Node cur = q.top();
q.pop();
//判断是否到达终点
if(cur == target)
return step;
//将cur相邻节点加入队列
for(Node x : cur.child)
if(visited.count(x) == 0)
{
q.push(x);
visited.insert(x);
}
}
//更新步数
step++;
}
}
题目练习
111. 二叉树的最小深度 - 简单
- start: 输入的根结点
- target: 结点的左右子树都为空
/**
* Definition for a binary tree node.
* struct TreeNode {
* int val;
* TreeNode *left;
* TreeNode *right;
* TreeNode() : val(0), left(nullptr), right(nullptr) {}
* TreeNode(int x) : val(x), left(nullptr), right(nullptr) {}
* TreeNode(int x, TreeNode *left, TreeNode *right) : val(x), left(left), right(right) {}
* };
*/
class Solution {
public:
int minDepth(TreeNode* root) {
queue<TreeNode*> q;
set<TreeNode*> visited;
q.push(root);
visited.insert(root);
int step = 1;
while(!q.empty())
{
int sz = q.size();
for(int i = 0; i<sz; ++i)
{
TreeNode* cur = q.front();
q.pop();
if(cur->left == nullptr && cur->right==nullptr)
return step;
if(cur->left != nullptr && visited.count(cur->left)==0)
{
q.push(cur->left);
visited.insert(cur->left);
}
if(cur->right != nullptr && visited.count(cur->right)==0)
{
q.push(cur->right);
visited.insert(cur->right);
}
}
step++;
}
return step;
}
};
因为是二叉树, 不需要记录结点是否被访问过, 代码中的visited集的相关部分可以省略.
剑指 Offer II 109. 开密码锁 - 中等
- 先根据框架写出代码, 检查是否能够遍历所有的密码组合
- 然后再添加密码对死亡密码的检测
class Solution {
public:
string plusOne(string cur, int i)
{
if(cur[i] == '9') cur[i] = '0';
else cur[i] += 1;
return cur;
}
string minusOne(string cur, int i)
{
if(cur[i] == '0') cur[i] = '9';
else cur[i] -= 1;
return cur;
}
int openLock(vector<string>& deadends, string target) {
queue<string> q;
set<string> visited;
//构建死亡密码集合
set<string> deadendsset(deadends.begin(), deadends.end());
q.push("0000");
visited.insert("0000");
int step = 0;
while(!q.empty())
{
int sz = q.size();
for(int i = 0; i<sz; ++i)
{
string cur = q.front();
q.pop();
//判断密码的合法性和是否等于目标
if(deadendsset.count(cur) == 1) continue;
if(cur == target) return step;
int s_sz = cur.size();
for(int j = 0; j<s_sz; ++j)
{
string cur_next = plusOne(cur, j);
if(visited.count(cur_next)==0)
{
q.push(cur_next);
visited.insert(cur_next);
}
cur_next = minusOne(cur, j);
if(visited.count(cur_next)==0)
{
q.push(cur_next);
visited.insert(cur_next);
}
}
}
step++;
}
//如果最终没有到达目标密码, 返回-1
return -1;
}
};