【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.樹是有向的因此不需要標誌是否訪問過,而對於無向圖而言,必須得標誌是否訪問過!並且為了防止某個節點多次入隊,需要在入隊前將其設定為已訪問!