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.
For example, given three buildings at (0,0)
, (0,4)
, (2,2)
, and an obstacle at (0,2)
:
1 - 0 - 2 - 0 - 1 | | | | | 0 - 0 - 0 - 0 - 0 | | | | | 0 - 0 - 1 - 0 - 0
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.
Analysis:
Simply BFS on every building point.
Solution:
1 public class Solution { 2 public void addPointToQueue(int[][] grid, int[][] sum, int[][] dis, boolean[][] visited, int curDis, 3 int nextX, int nextY, Queue<Point> q) { 4 int row = sum.length; 5 int col = sum[0].length; 6 if (nextX < 0 || nextX >= row || nextY < 0 || nextY >= col || visited[nextX][nextY] || grid[nextX][nextY] > 0) { 7 return; 8 } 9 10 visited[nextX][nextY] = true; 11 dis[nextX][nextY] = curDis + 1; 12 q.add(new Point(nextX, nextY)); 13 14 sum[nextX][nextY] += curDis + 1; 15 } 16 17 public void BuildingUpdate(int[][] grid, int[][] sum, boolean[][] allReachable, Point start) { 18 int row = grid.length; 19 int col = grid[0].length; 20 int[][] dis = new int[row][col]; 21 boolean[][] visited = new boolean[row][col]; 22 23 Queue<Point> q = new LinkedList<Point>(); 24 q.add(start); 25 while (!q.isEmpty()) { 26 Point cur = q.poll(); 27 int d = dis[cur.x][cur.y]; 28 29 addPointToQueue(grid, sum, dis, visited, d, cur.x - 1, cur.y, q); 30 addPointToQueue(grid, sum, dis, visited, d, cur.x + 1, cur.y, q); 31 addPointToQueue(grid, sum, dis, visited, d, cur.x, cur.y - 1, q); 32 addPointToQueue(grid, sum, dis, visited, d, cur.x, cur.y + 1, q); 33 } 34 35 // Check reachability 36 for (int i = 0; i < row; i++) 37 for (int j = 0; j < col; j++) 38 if (!visited[i][j]) { 39 allReachable[i][j] = false; 40 } 41 } 42 43 public int shortestDistance(int[][] grid) { 44 if (grid.length == 0 || grid[0].length == 0) 45 return -1; 46 47 int row = grid.length; 48 int col = grid[0].length; 49 int[][] sum = new int[row][col]; 50 boolean[][] allReachable = new boolean[row][col]; 51 for (int i = 0; i < row; i++) { 52 Arrays.fill(allReachable[i], true); 53 } 54 55 for (int i = 0; i < row; i++) 56 for (int j = 0; j < col; j++) 57 if (grid[i][j] == 1) { 58 BuildingUpdate(grid, sum, allReachable, new Point(i, j)); 59 } 60 61 int res = Integer.MAX_VALUE; 62 for (int i = 0; i < row; i++) 63 for (int j = 0; j < col; j++) 64 if (allReachable[i][j]) { 65 res = Math.min(res, sum[i][j]); 66 } 67 68 if (res == Integer.MAX_VALUE) 69 return -1; 70 return res; 71 } 72 }
Note: the code can be shorter, just I like this which makes the code clear and organized.