BFS的过程:
1.建图:邻接矩阵(二维数组)或邻接表(多个一维数组)
2.BFS搜索框架:
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
const int maxn=100;
bool vst[maxn][maxn]; // 访问标记
int dir[4][2]={0,1,0,-1,1,0,-1,0}; // 方向向量
struct State // BFS 队列中的状态数据结构
{
int x,y; // 坐标位置
int Step_Counter; // 搜索步数统计器
};
State a[maxn];
bool CheckState(State s) // 约束条件检验
{
if(!vst[s.x][s.y] && ...) // 满足条件
return 1;
else // 约束条件冲突
return 0;
}
void bfs(State st)
{
queue <State> q; // BFS 队列
State now,next; // 定义2 个状态,当前和下一个
st.Step_Counter=0; // 计数器清零
q.push(st); // 入队
vst[st.x][st.y]=1; // 访问标记
while(!q.empty())
{
now=q.front(); // 取队首元素进行扩展
if(now==G) // 出现目标态,此时为Step_Counter 的最小值
{
......
return;
}
for(int i=0 ; i<4 ; i++)
{
next.x=now.x+dir[i][0]; // 按照规则生成下一个状态
next.y=now.y+dir[i][1];
next.Step_Counter=now.Step_Counter+1; // 计数器加1
if(CheckState(next)) // 如果状态满足约束条件则入队
{
q.push(next);
vst[next.x][next.y]=1; //访问标记
}
}
q.pop(); // 队首元素出队
}
return;
}
题目:
1.LeetCode101
思路:
一次取出两个数;
注意:
1).先判断是否为NULL,再判断val是否相等
代码:
class Solution {
public:
bool isSymmetric(TreeNode* root) {
queue<TreeNode*> q ;
if(root == NULL) return true ;
q.push(root) ;
q.push(root) ;
while(!q.empty()) {
TreeNode* u1 = q.front() ;
q.pop() ;
TreeNode* u2 = q.front() ;
q.pop() ;
if(u1 == NULL && u2 == NULL) continue ;
if(u1 == NULL || u2 == NULL) return false ;
if(u1->val != u2->val) return false ;
q.push(u1->left) ;
q.push(u2->right) ;
q.push(u1->right) ;
q.push(u2->left) ;
}
return true ;
}
};
2.LeetCode103
思路:
for出每层,偶数层reverse
注意:
1).int q_length = q.size();for(int i = 0 ; i < q_length ; i ++ )
对
for(int i = 0 ; i < q.size() ; i ++ )
错
2).if(root == NULL) return ans ;
代码:
class Solution {
public:
vector<vector<int>> zigzagLevelOrder(TreeNode* root) {
vector<vector<int>> ans ;
queue<TreeNode*> q ;
if(root == NULL) return ans ;
q.push(root) ;
int cnt = 0 ;
while(!q.empty()) {
int size = q.size() ;
vector<int> ans0 ;
for(int i = 0 ; i < size ; i ++) {
TreeNode* u = q.front() ;
q.pop() ;
ans0.push_back(u->val) ;
if(u->left) q.push(u->left) ;
if(u->right) q.push(u->right) ;
}
if(cnt%2 == 1) reverse(ans0.begin() , ans0.end()) ;
ans.push_back(ans0) ;
cnt ++ ;
}
return ans ;
}
};
3.LeetCode111
代码:
class Solution {
public:
int minDepth(TreeNode* root) {
queue<TreeNode*> q ;
if(!root) return 0 ;
q.push(root) ;
int deep = 1 ;
while(!q.empty()) {
int size = q.size() ;
for( ; size > 0 ; size --) {
TreeNode* u = q.front() ;
q.pop() ;
if(!u->left && !u->right) return deep ;
if(u->left) q.push(u->left) ;
if(u->right) q.push(u->right) ;
}
deep ++ ;
}
return deep ;
}
};
4.LeetCode199
代码:
class Solution {
public:
vector<int> rightSideView(TreeNode* root) {
queue<TreeNode*> q ;
vector<int> ans ;
if(root == NULL) return ans ;
q.push(root) ;
while(!q.empty()) {
int size = q.size() ;
for(int i = 0 ; i < size ; i ++) {
TreeNode* u = q.front() ;
q.pop() ;
if(i == 0) ans.push_back(u->val) ;
if(u->right) q.push(u->right) ;
if(u->left) q.push(u->left) ;
}
}
return ans ;
}
};
5.LeetCode207(拓扑排序)
注意:
1).vector<vector<int>> graph(numCourses , vector<int>(numCourses)) ;
错 ;
vector<vector<int>> graph(numCourses) ;
对 ;
为啥?上面的那个规定了graph[i]的长度,但它可能没那么长,但是之后把graph[i]全遍历了一遍;
代码:
class Solution {
public:
bool canFinish(int numCourses, vector<vector<int>>& prerequisites) {
vector<int> degree(numCourses) ;
vector<vector<int>> graph(numCourses) ;
queue<int> q ;
if(prerequisites.size() == 0) return true ;
for(int i = 0 ; i < prerequisites.size() ; i ++) {
graph[prerequisites[i][1]].push_back(prerequisites[i][0]) ;
degree[prerequisites[i][0]] ++ ;
}
for(int i = 0 ; i < numCourses ; i ++) {
if(degree[i] == 0) q.push(i) ;
}
int cnt = 0 ;
while(!q.empty()) {
int temp = q.front() ;
q.pop() ;
cnt ++ ;
for(int i = 0 ; i < graph[temp].size() ; i ++) {
degree[graph[temp][i]] -- ;
if(degree[graph[temp][i]] == 0) q.push(graph[temp][i]) ;
}
}
return cnt == numCourses ;
}
};
6.LeetCode310(拓扑排序)
思路:
和上面那道题比较像,但是这道题是无序图,所以上面那道题需要入度表和出度对应表,但这道题不分出入度。从外层一层一层拨;
代码:
class Solution {
public:
vector<int> findMinHeightTrees(int n, vector<vector<int>>& edges) {
vector<int> degree(n , 0) ;
vector<vector<int>> graph(n) ;
queue<int> q ;
vector<int> ans ;
for(int i = 0 ; i < edges.size() ; i ++) {
graph[edges[i][0]].push_back(edges[i][1]) ;
graph[edges[i][1]].push_back(edges[i][0]) ;
degree[edges[i][0]] ++ ;
degree[edges[i][1]] ++ ;
}
int res = n ;
if(res == 1) ans.push_back(0) ;
for(int i = 0 ; i < n ; i ++) {
if(degree[i] == 1) q.push(i) ;
}
while(res != 1 && res != 2) {
int size = q.size() ;
res -= size ;
for(int i = 0 ; i < size ; i ++) {
int temp = q.front() ;
q.pop() ;
for(int j = 0 ; j < graph[temp].size() ; j ++) {
if(degree[graph[temp][j]] > 0) degree[graph[temp][j]] -- ;
if(degree[graph[temp][j]] == 1) q.push(graph[temp][j]) ;
}
}
}
while(!q.empty()) {
ans.push_back(q.front()) ;
q.pop() ;
}
return ans ;
}
};
7.LeetCode127
思路:
双向bfs,每次只挑短的那个遍历
代码:
class Solution {
public:
int ladderLength(string beginWord, string endWord, vector<string>& wordList) {
unordered_set<string> dict(wordList.begin() , wordList.end()) ;
unordered_set<string> beginset , endset , tmp , visited ;
if(dict.find(endWord) == dict.end()) return 0 ;
beginset.insert(beginWord) ;
endset.insert(endWord) ;
int len = 1 ;
while(!beginset.empty() && !endset.empty()) {
if(beginset.size() > endset.size()) {
tmp = beginset ;
beginset = endset ;
endset = tmp ;
}
tmp.clear() ;
for(auto word : beginset) {
for(int i = 0 ; i <word.size() ; i ++) {
char old = word[i] ;
for(char c = 'a' ; c <= 'z' ; c ++) {
word[i] = c ;
if(c == old) continue ;
else {
if(endset.find(word) != endset.end()) return len + 1 ;
if(visited.find(word) == visited.end() && dict.find(word) != dict.end()) {
tmp.insert(word) ;
visited.insert(word) ;
}
}
}
word[i] = old ;
}
}
beginset = tmp ;
len ++ ;
}
return 0 ;
}
};