传送门
题目分析:
对于只含有0和1的二维网路,题目实际上问的是二维网络中连通着的'1'的块数(这里的连通只能是上下左右连通)。那么,我们可以遍历二维网络,对于陆地(由'1'构成),搜索与其向连的'1'(陆地),$NumIsland$加一,当搜索完一块儿陆地(连着的'1')后,一定将他们变为'0',避免重复。
基于上述思想,做法有很多,比如搜索时用$bfs$和$dfs$均可,只不过$dfs$用递归实现,而$bfs$用队列实现。除此之外,也可以考虑用并查集实现相关连通块儿的合并,最后统计根节点的数目就行了。
方法一、深度优先搜索$dfs$
class Solution {public: int numIslands(vectorchar>>& grid) { int num_island = 0; for(int i = 0; i < grid.size(); i++) { for(int j = 0; j < grid[0].size(); j++) { if(grid[i][j] == '1') { num_island++; dfs(grid, i, j); } } } return num_island; } void dfs(vector char>>& grid, int x, int y) { int dx[4] = {-1,0,1,0}, dy[4] = {0,1,0,-1}; grid[x][y] = '0'; //避免重复遍历 //深度优先搜索(迭代) for(int i = 0; i < 4; i++) { int xx = x + dx[i], yy = y + dy[i]; if(xx >= 0 && xx < grid.size() && yy >= 0 && yy < grid[0].size() && grid[xx][yy] == '1') dfs(grid, xx, yy); } } };
方法二、广度优先搜索$bfs$
#includeusing namespace std; int dx[4] = {0,0,1,-1}; int dy[4] = {1,-1,0,0}; class Solution { public: int numIslands(vector char>>& grid) { int row = grid.size(); if(!row) return 0; int col = grid[0].size(); int num_island = 0; for(int i = 0; i < grid.size(); i++) { for(int j = 0; j < grid[0].size(); j++) { if(grid[i][j] == '1') { num_island++; grid[i][j] = '0'; //避免重复查找 queue int, int>> neighbors; neighbors.push({i, j}); while(!neighbors.empty()) { auto temp = neighbors.front(); neighbors.pop(); int x = temp.first, y = temp.second; for(int k = 0; k < 4; k++) { int xx = x + dx[k], yy = y + dy[k]; if(xx>=0 && xx =0 && yy 0].size()) { if (grid[xx][yy]=='1') { neighbors.push({xx, yy}); grid[xx][yy] = '0'; } } } } } } } return num_island; } };
方法三、并查集
#includeusing namespace std; int dx[4] = {0,0,1,-1}; int dy[4] = {1,-1,0,0}; int par[100005]; int rak[100005]; class Solution { public: void init(int n) { // 初始化 for(int i = 0; i < n; i++) { par[i] = i; rak[i] = 0; } } int find(int x) { // 寻找父亲节点 if(par[x] == x) return x; else return par[x]=find(par[x]); } void unite(int x, int y) { x = find(x); y = find(y); if(x == y) return ; //x,y已经在一颗树上 if(rak[x] < rak[y]) par[x] = y; else { par[y] = x; if (rak[x] == rak[y]) rak[x] ++; } } int numIslands(vector char>>& grid) { int row = grid.size(); if(!row) return 0; int col = grid[0].size(); int count = row * col; int num_island = 0; init(count); for(int i = 0; i < row; i++) for(int j = 0; j < col; j++) { if(grid[i][j] == '1') { grid[i][j] = '-1'; //最后还要统计根节点的数目 for(int k = 0; k < 4; k++) { int x = i + dx[k], y = j + dy[k]; if(x<0 || x>= row || y<0 || y>=col) continue; if(grid[x][y]=='1') { unite(i * col + j, x * col + y); } } } } for(int i = 0; i < row; i++) { for(int j = 0; j < col; j++) { if(par[i*col+j] == (i*col+j) && grid[i][j] !='0') num_island++; } } return num_island; } };