写在前面
DFS和BFS这是数据结构 图
最基本的两个算法,这里记录两道题的求解过程复习一下这两道算法
克隆图(leetcode133)
这题没什么说的,就是给你一个图,给出这个图的深度复制结果
深度优先
对于深度优先算法,最重要的是使用一个哈希表来维持visited
过的点,具体实现见代码:
/*
// Definition for a Node.
class Node {
public:
int val;
vector<Node*> neighbors;
Node() {
val = 0;
neighbors = vector<Node*>();
}
Node(int _val) {
val = _val;
neighbors = vector<Node*>();
}
Node(int _val, vector<Node*> _neighbors) {
val = _val;
neighbors = _neighbors;
}
};
*/
class Solution {
public:
unordered_map<Node*, Node*>visited;
Node* cloneGraph(Node* node) {
if (!node)return node;
Node* newnode = new Node(node->val, vector<Node*>());
if (visited.find(node) != visited.end()) {
return visited.find(node)->second;
}
visited[node] = newnode;
for (int i = 0; i < node->neighbors.size(); i++) {
if (visited.find(node->neighbors[i])==visited.end()) {
//visited[node->neighbors[i]] = new Node(node->neighbors[i]->val, vector<Node*>());
cloneGraph(node->neighbors[i]);
}
newnode->neighbors.push_back(visited.find(node->neighbors[i])->second);
}
return newnode;
}
};
注意
- visited的更新,是在for循环之外,for循环只是逐个调用这个递归的函数,不是在for循环里面执行
unordered_map
的用法find
如果找不到,会等于visited.end()
- 如果找到了,返回的是一个
iterator
,调用键值可以直接->second
这样子 - 存储可以直接
visited[a]=b
这样子
广度优先
广度优先的精华在于另外维护一个队列,每次从队列中取一个元素来遍历,区别在于,这样要在for循环中更新 visited
上代码
class Solution {
public:
Node* cloneGraph(Node* node) {
if (!node) return node;
unordered_map<Node*, Node*>visited;
queue<Node*>node_queue;
Node* newnode = new Node(node->val, vector<Node*>());
visited[node] = newnode;
node_queue.push(node);
while(!node_queue.empty()) {
Node *tmp = node_queue.front();
node_queue.pop();
for (int i = 0; i < tmp->neighbors.size(); i++) {
if (visited.find(tmp->neighbors[i]) == visited.end()) {
node_queue.push(tmp->neighbors[i]);
visited[tmp->neighbors[i]] = new Node(tmp->neighbors[i]->val, vector<Node*>());
}
visited.find(tmp)->second->neighbors.push_back(visited.find(tmp->neighbors[i])->second);
}
}
return newnode;
}
};
注意
- queue的用法,front和pop要分开使用
- visited在for循环内部更新
岛屿数量(leetcode200)
题目描述:
深度优先
这题也是很容易想到要图遍历,不过这个是需要从每一个点开始出发,如果是标注为1
的点,那么对应岛屿数量就要加一个,对每一个岛屿进行处理,上下左右遍历,能走的都要走遍
注意这题可以把grid
直接当成visited
来使用,只要是1
那么就是没有访问过的,访问后置为0
,就可以省下一部分空间
上代码
class Solution {
public:
vector<vector<int>>directions = {{0,1}, {1,0}, {-1, 0}, {0, -1}};
vector<vector<int>>visited;
int row;
int col;
int numIslands(vector<vector<char>>& grid) {
if (grid.size() <= 0)return 0;
int row = grid.size();
int col = grid[0].size();
this->row = row;
this->col = col;
vector<vector<int>>visited(row, vector<int>(col));
int count = 0;
this->visited = visited;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
//visited[i][j] = 0;
if (grid[i][j] == '1' && !this->visited[i][j]){
count++;
dfs(grid, i, j);
}
}
}
return count;
}
bool isIn(int x, int y) {
return x>=0 && x <this->row && y>=0 &&y<this->col;
}
void dfs(vector<vector<char>>& grid, int oldi, int oldj) {
this->visited[oldi][oldj] = 1;
for (int i = 0; i < 4; i ++) {
int newx = oldi + directions[i][0];
int newy = oldj + directions[i][1];
if (isIn(newx, newy) && grid[newx][newy] == '1' && !visited[newx][newy]){
dfs(grid, newx,newy);
}
}
}
};
广度优先
这个广度优先,和第133题其实差不多,就是又学会了一招pair
和相应的second, first
,废话不说,直接上代码:
class Solution {
public:
vector<vector<int>>directions = {{0,1}, {1,0}, {-1, 0}, {0, -1}};
vector<vector<int>>visited;
int row;
int col;
int numIslands(vector<vector<char>>& grid) {
if (grid.size() <= 0)return 0;
int row = grid.size();
int col = grid[0].size();
int count = 0;
for (int i = 0; i < grid.size(); i++) {
for (int j = 0; j < grid[0].size(); j++) {
if (grid[i][j] == '1' ){
count++;
queue<pair<int, int>>node_queue;
node_queue.push({i,j});
while(!node_queue.empty()) {
auto kk = node_queue.front();
node_queue.pop();
int r=kk.first;
int c = kk.second;
if (r + 1 < row && grid[r + 1][c] == '1') {
node_queue.push({r + 1, c});
grid[r + 1][c] = '0';
}
if (r - 1 >= 0 && grid[r - 1][c] == '1') {
node_queue.push({r - 1, c});
grid[r - 1][c] = '0';
}
if (c + 1 < col && grid[r][c + 1] == '1') {
node_queue.push({r, c + 1});
grid[r][c + 1] = '0';
}
if (c - 1 >= 0 && grid[r][c - 1] == '1') {
node_queue.push({r, c - 1});
grid[r][c - 1] = '0';
}
}
}
}
}
return count;
}
};