【探索-中級演算法】島嶼的個數
阿新 • • 發佈:2019-02-18
最開始想到的解決方法,就是藉助一個輔助陣列 boolean[][] map
,其中 map[i][j]==true
表示該土地已經被訪問過了,且再借助深度遍歷,當遇到一塊土地時,同時把與其相連的土地都給遍歷掉。
public int numIslands(char[][] grid) {
if (grid==null||grid.length==0||grid[0].length==0) return 0;
boolean[][] map = new boolean[grid.length][grid[0].length];
// map[i][j] 為 true 則表示遍歷過了
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j]=='1'&&!map[i][j]) {
++count;
travers(grid, map, i, j);
}
}
}
return count;
}
public void travers (char[][] grid, boolean[][] map, int i, int j) {
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) return;
// 如果不是陸地,或者已經被遍歷過了
if (grid[i][j]=='0'||map[i][j]) return;
map[i][j] = true;
// 遍歷周圍
travers(grid, map, i - 1, j);
travers(grid, map, i + 1, j);
travers (grid, map, i, j - 1);
travers(grid, map, i, j + 1);
}
之後,看到提交的答案中,有一個更加快的提交,即藉助原地演算法,如果 grid[i][j]
被遍歷了,則用一個非 0
和 1
的值(避免影響原本的判斷)去設定,用於標記已經被遍歷了。
// 直接使用原地演算法,就不用開闢輔助空間
public int numIslands(char[][] grid) {
if (grid==null||grid.length==0||grid[0].length==0) return 0;
// map[i][j] 為 true 則表示遍歷過了
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j]=='1') {
++count;
travers(grid, i, j);
}
}
}
return count;
}
private void travers(char[][] grid, int i, int j) {
if (i < 0 || i >= grid.length || j < 0 || j >= grid[0].length) return;
if (grid[i][j]=='0'||grid[i][j]=='2') return;
grid[i][j] = '2';
// 遍歷周圍
travers(grid, i - 1, j);
travers(grid, i + 1, j);
travers(grid, i, j - 1);
travers(grid, i, j + 1);
}
當然,最後腦洞開了一下,用迭代代替遞迴。不過請勿模仿,因為 grid 太大的話就會超時。不過皮一下很開心。
// 不用遞迴的話進行遍歷的話,則可以用一個集合,儲存該點與周圍及其周圍的周圍的點,直到遍歷完這個集合
public int numIslands(char[][] grid) {
if (grid==null||grid.length==0||grid[0].length==0) return 0;
LinkedList<Point> tmpPoints = new LinkedList<>();
int count = 0;
for (int i = 0; i < grid.length; i++) {
for (int j = 0; j < grid[0].length; j++) {
if (grid[i][j]=='1') {
++count;
tmpPoints.offer(new Point(i, j));
while (!tmpPoints.isEmpty()) {
Point point = tmpPoints.poll();
int tmpX = point.x;
int tmpY = point.y;
grid[tmpX][tmpY] = '2';
if ((tmpX-1)>=0&&grid[tmpX-1][tmpY]=='1')
tmpPoints.offer(new Point(tmpX - 1, tmpY));
if ((tmpX+1)<grid.length&&grid[tmpX+1][tmpY]=='1')
tmpPoints.offer(new Point(tmpX + 1, tmpY));
if ((tmpY-1)>=0&&grid[tmpX][tmpY-1]=='1')
tmpPoints.offer(new Point(tmpX , tmpY-1));
if ((tmpY+1)<grid[0].length&&grid[tmpX][tmpY+1]=='1')
tmpPoints.offer(new Point(tmpX , tmpY+1));
}
}
}
}
return count;
}