BFS 1 - Graph Traversal
BFS in Graph vs. BFS in Tree: 无向图 vs. 有向图; 需要标记数组 vs. 不需要
时间复杂度:O(m + n),m是边数,n是点数
1. Number of Islands
Given a boolean 2D matrix, 0 is represented as the sea, 1 is represented as the island. If two 1 is adjacent, we consider them in the same island. We only consider up/down/left/right adjacent.
Find the number of islands.
void bfs(vector<vector<bool>> &grid, int starti, int startj) {
queue<pair<int, int>> q;
q.push(make_pair(starti, startj));
int neibor[4][2] {-1, 0, 1, 0, 0, -1, 0, 1};
while(!q.empty()) {
auto tmp = q.front();
q.pop();
grid[tmp.first][tmp.second] = 0; // 记得标记
for(int i = 0; i < 4; i++) {
int nextx = tmp.first + neibor[i][0];
int nexty = tmp.second + neibor[i][1];
// 不要忘了先判断边界,否则会越界访问grid
if(nextx >= 0 && nextx < grid.size() && nexty >= 0 && nexty < grid[0].size() && grid[nextx][nexty] == 1) {
grid[nextx][nexty] = 0; // !!放的时候就标记,记得标记,会优化时间!防止重复进来
q.push(make_pair(nextx, nexty));
}
}
}
}
int numIslands(vector<vector<bool>> &grid) {
// 1. 找这个矩阵里的第一个1,放到queue里
// 2. bfs开始找,然后弄成0
// 3. 重复上述2步,直到矩阵没有1
if (grid.size() == 0) return 0;
if (grid[0].size() == 0) return 0;
int num = 0, rows = grid.size(), cols = grid[0].size();
int num_island = 0;
for(int i = 0; i < rows; i++) {
for(int j = 0; j < cols; j++) {
if(grid[i][j] == 1) {
num_island++;
bfs(grid, i, j);
}
}
}
return num_island;
}
2. Search Graph Nodes
Given a undirected graph, a node and a target, return the nearest node to given node which value of it is target, return NULL if you can't find.
UndirectedGraphNode* searchNode(vector<UndirectedGraphNode*>& graph,
map<UndirectedGraphNode*, int>& values,
UndirectedGraphNode* node,
int target) {
if(graph.size() == 0) return NULL;
queue<UndirectedGraphNode*> q;
unordered_set<UndirectedGraphNode*> visited;
q.push(node);
visited.insert(node);
while(!q.empty()) {
UndirectedGraphNode *cur = q.front();
q.pop();
if(values[cur] == target) return cur; // 弹出的时候,判断结果
for(auto n: cur->neighbors) {
if(visited.find(n) != visited.end()) continue;
q.push(n);
visited.insert(n); // 放的时候就标记
}
}
return NULL;
}
3. Graph Valid Tree
Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each
edge is a pair of nodes), write a function to check whether these edges make up
a valid tree.
You can assume that no duplicate edges will appear in edges. Since all edges are
undirected, [0, 1] is the same as [1, 0] and thus will not appear together in
edges.
Example
Given n = 5 and edges = [[0, 1], [0, 2], [0, 3], [1, 4]], return true.
Given n = 5 and edges = [[0, 1], [1, 2], [2, 3], [1, 3], [1, 4]], return false.
bool validTree(int n, vector<vector<int>>& edges) {
int nedges = edges.size();
// 边数对,且从任意一点,能遍历到所有节点
if (nedges != n - 1) return false;
set<int> nodes;
unordered_map<int, vector<int>> orders;
for (int i = 0; i < nedges; i++) {
orders[edges[i][0]].push_back(edges[i][1]);
orders[edges[i][1]].push_back(edges[i][0]);
}
queue<int> q;
q.push(0);
nodes.insert(0); // just pick one to start
while (!q.empty()) {
int cur = q.front();
q.pop();
for (auto i : orders[cur]) {
// !! nodes可以充当visited的角色,不需要再开一个visited了
if (nodes.find(i) != nodes.end()) continue;
nodes.insert(i);
q.push(i);
}
}
return nodes.size() == n;
}
Union-Find algorithm
bool validTree(int n, vector<vector<int>>& edges) {
vector<int> root(n, -1);
for (int i = 0; i < edges.size(); i++) {
int root1 = find(root, edges[i][0]);
int root2 = find(root, edges[i][1]);
if (root1 == root2) return false;
root[root1] = root2;
}
return edges.size() == n - 1;
}
int find(vector<int>& root, int e) {
if (root[e] == -1)
return e;
else
return root[e] = find(root, root[e]);
}
4.Clone Graph
/**
* Definition for undirected graph.
* struct UndirectedGraphNode {
* int label;
* vector<UndirectedGraphNode *> neighbors;
* UndirectedGraphNode(int x) : label(x) {};
* };
*/
UndirectedGraphNode *cloneGraph(UndirectedGraphNode *node) {
if (node == NULL) return NULL;
// 1. BFS: Get list of all the nodes
// 2. Copy these nodes, and get hash map: old->new
unordered_map<UndirectedGraphNode *, UndirectedGraphNode *> corres;
unordered_set<UndirectedGraphNode *> visited;
queue<UndirectedGraphNode *> q;
q.push(node);
visited.insert(node); // 图的BFS一定注意有visited
while (!q.empty()) {
UndirectedGraphNode *cur = q.front();
corres[cur] = new UndirectedGraphNode(cur->label);
q.pop();
for (auto i : cur->neighbors) {
if (visited.find(i) != visited.end()) continue;
q.push(i);
visited.insert(i);
}
}
// 3. Copy the edges.
for (auto i : corres) {
for (auto j : i.first->neighbors) {
i.second->neighbors.push_back(corres[j]); // push corres[j]
}
}
return corres[node];
}