原题链接在这里: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), t
he 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 }