LeetCode 317. Shortest Distance from All Buildings

原题链接在这里:https://leetcode.com/problems/shortest-distance-from-all-buildings/

题目:

You want to build a house on an empty land which reaches all buildings in the shortest amount of distance. You can only move up, down, left and right. You are given a 2D grid of values 0, 1 or 2, where:

  • Each 0 marks an empty land which you can pass by freely.
  • Each 1 marks a building which you cannot pass through.
  • Each 2 marks an obstacle which you cannot pass through.

Example:

Input: [[1,0,2,0,1],[0,0,0,0,0],[0,0,1,0,0]]

1 - 0 - 2 - 0 - 1
|   |   |   |   |
0 - 0 - 0 - 0 - 0
|   |   |   |   |
0 - 0 - 1 - 0 - 0

Output: 7 

Explanation: Given three buildings at (0,0), (0,4), (2,2), and an obstacle at (0,2),
             the point (1,2) is an ideal empty land to build a house, as the total 
             travel distance of 3+3+1=7 is minimal. So return 7.

Note:
There will be at least one building. If it is not possible to build such house according to the above rules, return -1.

题解:

从每一座building开始做BFS, 更新每个空地达到building的距离总和 以及 每个空地能到达building的个数.

第二次扫描grid, 若是空地并且它能到达的building数目是总共的building数目,就更新min距离.

Note: For the second iteration, check 2 conditions. grid[i][j] < 0 && reachCount[i][j] = totalCount.

Time Complexity: O(m^2 * n^2), 每次BFS用O(mn), 一共做了m*n次BFS.

Space: O(m*n)

AC Java:

 1 class Solution {
 2     public int shortestDistance(int[][] grid) {
 3         if(grid == null || grid.length == 0 || grid[0].length == 0){
 4             return 0;
 5         }
 6         
 7         int m = grid.length;
 8         int n = grid[0].length;
 9         
10         //记录每个点能够到达building的个数
11         int [][] reachCount = new int[m][n];
12         int totalCount = 0;
13         
14         for(int i = 0; i<m; i++){
15             for(int j = 0; j<n; j++){
16                 if(grid[i][j] == 1){
17                     //遇到building, 从这个building开始做bfs
18                     totalCount++;
19                     bfs(grid, i, j, reachCount);
20                 }
21             }
22         }
23         
24         int res = Integer.MAX_VALUE;
25         for(int i = 0; i<m; i++){
26             for(int j = 0; j<n; j++){
27                 if(grid[i][j] < 0 && reachCount[i][j] == totalCount){
28                     res = Math.min(res, -grid[i][j]);
29                 }
30             }
31         }
32         
33         return res == Integer.MAX_VALUE ? -1 : res;
34     }
35     
36     int [][] dirs = new int[][]{{-1, 0}, {1, 0}, {0, -1}, {0, 1}};
37     private void bfs(int [][] grid, int i, int j, int [][] reachCount){
38         int level = 0;
39         int m = grid.length;
40         int n = grid[0].length;
41         LinkedList<int []> que = new LinkedList<>();
42         boolean[][] visited = new boolean[m][n];
43         que.add(new int[]{i, j});
44         visited[i][j] = true;
45         
46         while(!que.isEmpty()){
47             int size = que.size();
48             while(size-- > 0){
49                 int [] cur = que.poll();
50                 grid[cur[0]][cur[1]] -= level;
51                 reachCount[cur[0]][cur[1]]++;
52                 
53                 for(int [] dir : dirs){
54                     int x = cur[0] + dir[0];
55                     int y = cur[1] + dir[1];
56                     if(x < 0 || x >=m || y < 0 || y >=n || visited[x][y] || grid[x][y] > 0){
57                         continue;
58                     }
59 
60                     que.add(new int[]{x, y});
61                     visited[x][y] = true;
62                 }
63             }
64             
65             level++;
66         }
67     }
68 }
原文地址:https://www.cnblogs.com/Dylan-Java-NYC/p/5318029.html