Leetcode200.岛屿数量
给你一个由 ‘1’(陆地)和 ‘0’(水)组成的的二维网格,请你计算网格中岛屿的数量。
岛屿总是被水包围,并且每座岛屿只能由水平方向和/或竖直方向上相邻的陆地连接形成。
此外,你可以假设该网格的四条边均被水包围。
示例1:
输入:grid = [
[“1”,“1”,“1”,“1”,“0”],
[“1”,“1”,“0”,“1”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“0”,“0”,“0”]
]
输出:1
示例2:
输入:grid = [
[“1”,“1”,“0”,“0”,“0”],
[“1”,“1”,“0”,“0”,“0”],
[“0”,“0”,“1”,“0”,“0”],
[“0”,“0”,“0”,“1”,“1”]
]
输出:3
方法一:广度优先遍历
- 按行列的顺序依次遍历二维数组,每遍历到一个1,说明涉足到一片新陆地,答案ans+1。
- 对当前探索到的陆地进行广度优先搜索,建立队列,将刚涉足的1坐标入队,探索该坐标块上下左右(套用模板,双数组建立四周坐标,注意判断是否越界),将满足条件且值为1的陆地坐标块入队,同时设置该坐标块为0,避免后续重复遍历。
- 探索完该坐标块,将坐标块出队 ,对下一个队首元素进行广度优先搜索,转步骤2,直至队列为空。
- 队列为空说明探索完了一整片大陆,转步骤1,探索新的大陆。
代码
class Solution {
public:
int numIslands(vector<vector<char>>& grid) {
int Xi[4]={0, 1, 0, -1};
int Yi[4]={1, 0, -1, 0};
int height = grid.size();
if(height==0) return 0;
int width = grid[0].size();
int ans = 0;
queue<pair<int,int>> q;
for(int i=0;i<height;i++){
for(int j=0;j<width;j++){
if(grid[i][j]=='1'){
grid[i][j]='0';
ans+=1;
q.emplace(i,j);
while(!q.empty()){
int x = q.front().first;
int y = q.front().second;
for(int t=0;t<4;t++){
int xi = x+Xi[t];
int yi = y+Yi[t];
if(xi>=0&&xi<height&&yi>=0&&yi<width&&grid[xi][yi]=='1'){
q.emplace(xi,yi);
grid[xi][yi] = '0';
}
}
q.pop();
}
}
}
}
return ans;
}
};
方法二:深度优先遍历(暂时一知半解勉强可以做出来,理解还不透彻,解析待补充)
代码
在这里插入代码片class Solution {
public:
void dfs(vector<vector<char>>& grid,int x,int y){
int height = grid.size();
int width = grid[0].size();
grid[x][y] = '0';
int dx[4] = {1,-1,0,0};
int dy[4] = {0,0,-1,1};
for(int i=0;i<4;i++){
int xi = x+dx[i],yi = y+dy[i];
if(xi>=0&&xi<height&&yi>=0&&yi<width&&grid[xi][yi]=='1'){
dfs(grid,xi,yi);
}
}
}
int numIslands(vector<vector<char>>& grid) {
int height = grid.size();
if(height==0) return 0;
int width = grid[0].size();
int ans = 0;
for(int i=0;i<width;i++){
for(int j=0;j<height;j++){
if(grid[j][i]=='1'){
ans+=1;
dfs(grid,j,i);
}
}
}
return ans;
}
};
Leetcode547.省份数量
示例1:
输入:isConnected = [[1,1,0],[1,1,0],[0,0,1]]
输出:2
示例2:
输入:isConnected = [[1,0,0],[0,1,0],[0,0,1]]
输出:3
方法一:广度优先遍历
- 设置标记数组flag,用于记录城市是否被搜索过,初始值均设为0。
- 遍历flag探索每一个城市,每遍历到一个1,说明探索到一个新省份的第一个城市,答案ans+1。
- 对当前探索到的省份进行广度优先搜索,建立队列,将刚涉足的城市下标入队,访问二维数组isConnected[][]中以该城市为出发点的城市(如判断与城市3相邻的城市,遍历t访问isConnected[3][t]即可),将满足条件(isConnected中值为1)且flag值为1的城市下标入队,同时设置该flag数组中该下标位置为0,避免后续重复访问。
- 探索完该城市,将城市坐标出队 ,对下一个队首元素(即周边城市)进行广度优先搜索,转步骤2,直至队列为空。
- 队列为空说明探索完了一整个省份,转步骤1,探索新省份的第一个城市。
代码
class Solution {
public:
int findCircleNum(vector<vector<int>>& isConnected) {
int nums = isConnected.size();
int ans = 0;
int flag[nums];
memset(flag,0,sizeof(flag));
queue<int> q;
for(int i=0;i<nums;i++){
if(flag[i]==0){
ans+=1;
flag[i]=1;
q.push(i);
while(!q.empty()){
int j = q.front();
q.pop();
for(int t=0;t<nums;t++){
if(isConnected[j][t]==1&&flag[t]==0){
q.push(t);
flag[t]=1;
}
}
}
}
}
return ans;
}
};
方法二:深度优先遍历(暂时一知半解勉强可以做出来,理解还不透彻,解析待补充)
代码
class Solution {
public:
int flag[201]={0};//全局数组,可以这样赋初值为0,局部数组则需要memset函数
void dfs(vector<vector<int>>& isConnected,int i){
int nums = isConnected.size();
for(int t=0;t<nums;t++){
if(flag[t]==0&&isConnected[i][t]==1){
flag[t]=1;
dfs(isConnected,t);
}
}
}
int findCircleNum(vector<vector<int>>& isConnected) {
int nums = isConnected.size();
if(nums==0) return 0;
int ans = 0;
for(int i=0;i<nums;i++){
if(flag[i]==0){
flag[i] = 1;
ans+=1;
dfs(isConnected,i);
}
}
return ans;
}
};