1. 程式人生 > >【探索-中級演算法】島嶼的個數

【探索-中級演算法】島嶼的個數

在這裡插入圖片描述

最開始想到的解決方法,就是藉助一個輔助陣列 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] 被遍歷了,則用一個非 01 的值(避免影響原本的判斷)去設定,用於標記已經被遍歷了。

// 直接使用原地演算法,就不用開闢輔助空間
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;
}