1. 程式人生 > 其它 >【LeetCode】1162. 地圖分析

【LeetCode】1162. 地圖分析

1162. 地圖分析

知識點:圖;遞迴

題目描述

你現在手裡有一份大小為N x N 的 網格 grid,上面的每個 單元格 都用0和1標記好了。其中0代表海洋,1代表陸地,請你找出一個海洋單元格,這個海洋單元格到離它最近的陸地單元格的距離是最大的。

我們這裡說的距離是「曼哈頓距離」(Manhattan Distance):(x0, y0) 和(x1, y1)這兩個單元格之間的距離是|x0 - x1| + |y0 - y1|。

如果網格上只有陸地或者海洋,請返回-1。

示例
輸入:[[1,0,1],[0,0,0],[1,0,1]]
輸出:2
解釋: 
海洋單元格 (1, 1) 和所有陸地單元格之間的距離都達到最大
最大距離為 2。
輸入:[[1,0,0],[0,0,0],[0,0,0]]
輸出:4
解釋: 
海洋單元格 (2, 2) 和所有陸地單元格之間的距離都達到最大,最大距離為 4。

解法一:廣度優先(BFS)

樹的BFS:先把root節點入隊,然後再一層一層的遍歷。
圖的BFS也是一樣的,與樹的BFS的區別是:
1.樹只有一個root,而圖可以有多個源點,所有首先需要將多個源點入隊。
2.樹是有向的因此不需要標誌是否訪問過,而對於無向圖而言,必須得標誌是否訪問過!並且為了防止某個節點多次入隊,需要在入隊前將其設定為已訪問

樹的廣度優先搜尋:從root開始往子節點上;
一個源點的廣度優先和多個源點的廣度優先,參考下面連結

廣度優先搜尋

這道題目就是多源廣度優先搜尋的樣題,我們尋找離陸地最遠的海洋單元格,可以將其轉化為從所有的陸地開始一輪一輪的往外擴,最後的就是最遠的。
第一輪變化以各個陸地為起點,走一格就能到達的海域;第二輪變化是在第一輪的基礎上走兩格能到達的海域,這樣子不斷變化,越到後面沒有被覆蓋的海域離陸地的距離最遠,也越接近我們想找到的那個海域,直到地圖被全覆蓋。

class Solution {
    public int maxDistance(int[][] grid) {
        //把所有的陸地先入隊;
        int[] dx = {0, 0, 1, -1};
        int[] dy = {1, -1, 0, 0}; //設定四個變化方向;
        Queue<int[]> queue = new LinkedList<>();
        int m = grid.length, n = grid[0].length;
        for(int i = 0; i < m; i++){
            for(int j = 0; j < n; j++){
                if(grid[i][j] == 1){
                    queue.add(new int[]{i, j});
                }
            }
        }
        if(queue.size() == 0 || queue.size() == m*n) return -1; //沒有陸地或海洋;
        //從各個陸地一圈一圈向外擴,最後就是最遠的;
        int[] point = null; //出隊點;
        while(!queue.isEmpty()){
            point = queue.poll();
            //求出此座標的四個相鄰座標;
            int x = point[0], y = point[1];
            for(int i = 0; i < 4; i++){
                int newX = x + dx[i];
                int newY = y + dy[i];
                if(newX < 0 || newX >= m || newY < 0 || newY >= n || grid[newX][newY] != 0){
                    continue; //剔除無效座標和周圍陸地;
                }
                grid[newX][newY] = grid[x][y]+1; //向外擴;
                queue.add(new int[]{newX, newY});
            }
        }
        return grid[point[0]][point[1]]-1; //返回最後一次出隊的座標點;
    }
}

體會

樹的BFS:先把root節點入隊,然後再一層一層的遍歷。
圖的BFS也是一樣的,與樹的BFS的區別是:
1.樹只有一個root,而圖可以有多個源點,所有首先需要將多個源點入隊。
2.樹是有向的因此不需要標誌是否訪問過,而對於無向圖而言,必須得標誌是否訪問過!並且為了防止某個節點多次入隊,需要在入隊前將其設定為已訪問!

相關連結

地圖分析