Leetcode: 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.
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.

Start from each building, do bfs to calculate the shortest distance to each empty land which it can reach.

Repeat this process for all buildings. we can get the sum of shortest distance from every '0' to all reachable buildings. This value is stored in 'distance[][]'. 

Notice that there are empty lands that can not be reached from some buildings. like (0, 2) below, it can not be reached from the building (0, 0) and (2, 2)

1 1 0

0 0 1

0 0 1

Therefore, we also count how many building each '0' can be reached. It is stored in reach[][]. This can be done during the BFS. We also need to count how many total buildings are there in the matrix, which is stored in 'buildingNum'.

Our building should be placed at those empty places which can reach all buildings, that is to say, reach[i][j] == buildingNum

we choose the shortest distances among all these empty places.

Be careful the case where there are only buildings and no empty lands, like [[1]]. so shortest distance at last is still Integer.MAX_VALUE should be turned to -1

Syntax: use direction matrix can save lines of codes

 1 public class Solution {
 2     public int shortestDistance(int[][] grid) {
 3         if (grid==null || grid.length==0 || grid[0].length==0) return -1;
 4         int m = grid.length;
 5         int n = grid[0].length;
 6         int[][] dist = new int[m][n];
 7         int[][] reach = new int[m][n];
 8         int houseNum = 0;
 9         int[][] directions = {{-1,0},{1,0},{0,-1},{0,1}};
10         
11         for (int i=0; i<m; i++) {
12             for (int j=0; j<n; j++) {
13                 if (grid[i][j] == 1) {
14                     houseNum++;
15                     int level = 0;
16                     boolean[][] visited = new boolean[m][n];
17                     LinkedList<Integer> queue = new LinkedList<Integer>();
18                     queue.offer(i*n+j);
19                     visited[i][j] = true;
20                     while (!queue.isEmpty()) {
21                         int size = queue.size();
22                         for (int t=0; t<size; t++) {
23                             int cur = queue.poll();
24                             int x = cur/n;
25                             int y = cur%n;
26                             for (int[] dir : directions) {
27                                 int xnew = x + dir[0];
28                                 int ynew = y + dir[1];
29                                 if (xnew>=0 && xnew<m && ynew>=0 && ynew<n && !visited[xnew][ynew] && grid[xnew][ynew]==0) {
30                                     queue.offer(xnew*n+ynew);
31                                     visited[xnew][ynew] = true;
32                                     dist[xnew][ynew] += level+1;
33                                     reach[xnew][ynew]++;
34                                 }
35                             }
36                         }
37                         level++;
38                     }
39                 }
40             }
41         }
42         
43         int minDist = Integer.MAX_VALUE;
44         for (int i=0; i<m; i++) {
45             for (int j=0; j<n; j++) {
46                 if (grid[i][j]==0 && reach[i][j] == houseNum) {
47                     minDist = Math.min(minDist, dist[i][j]);
48                 }
49             }
50         }
51         return minDist==Integer.MAX_VALUE? -1 : minDist;
52     }
53 }

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值