整体思路
- 在输入的图中,首先选取一个可以走的点。(是陆地,且没有被访问过)
- 然后根据这一个点,使用BFS或者DFS向四周去扩张,把所有能扩张的全访问一遍
- 最终,最上层找到几个能访问的点,就是几个独立岛屿
- 这个题目说白了就是图的寻找连通块一样
题目细节
- 使用方向数组表示行进方向
- 上 左,下,右
- dx = {-1, 0, 0, 1}
- dy = {0, -1, 1, 0}
class Solution {
//记录一下子输入数据,省着下传了
private char[][] grid;
//记录一下子行数和列数,作为共享变量
int rowNum;
int colNum;
//创建一个和输入一样大小的二维数组,以此记录一个点是否被访问过
boolean[][] vistied;
public int numIslands(char[][] grid) {
this.grid = grid;
this.rowNum = grid.length;
this.colNum = grid[0].length;
vistied = new boolean[rowNum][colNum];
//答案
int ans = 0;
//遍历整个输入的二维数组,选取一个没有被访问过的且为1的点,然后使用bfs去四周扩张,只到把可访问的点全部扩张完成且访问
for(int i = 0;i < rowNum;i++){
for(int j = 0;j < colNum;j++){
if(grid[i][j] == '1' && !vistied[i][j]){
//答案+1 找到一个没有被访问的过岛屿,答案就加一。这是因为下面bfs会把找到的每一个岛屿全访问完的
//所以只要找到的岛屿,就是新的岛屿
ans++;
bfs(i,j);
}
}
}
return ans;
}
public void bfs(int x,int y){
//只要是广度优先遍历,就先把队列拿出来
Queue<Pair<Integer,Integer>> queue = new LinkedList<>();
//方向数组(记录行进方向的值),也就是x y + 方向数组的值 = 下一个点的坐标
// 上, 左, 右,下
int[] dx = new int[]{-1, 0, 0, 1};
int[] dy = new int[]{0, -1, 1, 0};
//把当前点放入队列中去
queue.add(new Pair<>(x,y));
while (!queue.isEmpty()){
//1:队头出队,记录当前点
Pair<Integer, Integer> point = queue.poll();
int nowX = point.getKey();
int nowY = point.getValue();
//记录这个点已经被访问过了
vistied[nowX][nowY] = true;
//2:以当前点为圆心,想上下左右扩张,能走的地方就标记访问
for(int i = 0;i < 4; i++){
//获取到当前点的下一个方向的点的坐标
int nextX = nowX + dx[i];
int nextY = nowY + dy[i];
//如果新的点超过边界了,就忽略这个点
if(nextX < 0 || nextX >= rowNum || nextY < 0 || nextY >= colNum){
continue;
}
//如果新的点不是岛屿则忽略这给点
if(grid[nextX][nextY] != '1'){
continue;
}
//如果新的点已经被访问过了则忽略这个点
if(vistied[nextX][nextY]){
continue;
}
//如果上面条件都不满足,说明是新点是一个没被访问的合法的陆地,那么就把这个点入队让他继续扩张去,然后记录已访问
queue.add(new Pair<>(nextX,nextY));
vistied[nextX][nextY] = true;
}
}
}
}