之前听朋友说LeetCode出了一道新题,但是一直在TLE,我就找时间做了一下。这题是一个比较典型的BFS的题目,自己匆忙写了一个答案,没有考虑优化的问题,应该是有更好的解法的。

原题如下:

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.

 

基本想法就是从每个数值为1的点做bfs,遇到为0的点就加上相应的距离。这题因为要求到所有1的距离和最小的点,所以就可以无脑iterate over所有数值为1的点,并开一个二维数组来记录各个点的累加距离值。最后要检查一下所有结果中的值,确保其可以reach到所有的值为1的点,若不存在这样的,则返回-1。代码如下,比较冗长,等有机会再优化一下吧。

 1 public class Solution {
 2     public int shortestDistance(int[][] grid) {
 3         int result = Integer.MAX_VALUE;
 4         boolean[][] done = new boolean[grid.length][grid[0].length];
 5         int[][] cost = new int[grid.length][grid[0].length];
 6         int[][] count = new int[grid.length][grid[0].length];
 7         int total = 0; // total # of 1
 8         for (int i = 0; i < grid.length; i++) {
 9             for (int j = 0; j < grid[0].length; j++) {
10                 done[i][j] = grid[i][j] != 0;
11                 total = grid[i][j] == 1 ? total + 1 : total;
12             }
13         }
14         for (int i = 0; i < grid.length; i++) {
15             for (int j = 0; j < grid[0].length; j++) {
16                 if (grid[i][j] == 1) {
17                     Deque<Integer> row = new ArrayDeque<>();
18                     Deque<Integer> col = new ArrayDeque<>();
19                     enqueue(row, col, i, j, done, grid);
20                     bfs(row, col, grid, cost, done, count, 1);
21                 }
22             }
23         }
24         if (!isValid(count, total)) {
25             return -1;
26         }
27         for (int i = 0; i < cost.length; i++) {
28             for (int j = 0; j < cost[0].length; j++) {
29                 if (count[i][j] == total) {
30                     result = cost[i][j] > 0 ? Math.min(result, cost[i][j]) : result;
31                 }
32             }
33         }
34         return result;
35     }
36 
37     private void bfs(Deque<Integer> row, Deque<Integer> col, int[][] grid, int[][] cost, boolean[][] done, int[][] count, int distance) {
38         if (row.isEmpty()) {
39             return;
40         }
41         int size = row.size();
42         List<Integer> row1 = new ArrayList<>();
43         List<Integer> col1 = new ArrayList<>();
44         for (int k = 0; k < size; k++) {
45             int i = row.poll();
46             int j = col.poll();
47             row1.add(i);
48             col1.add(j);
49             cost[i][j] += distance;
50             count[i][j] += 1;
51             enqueue(row, col, i, j, done, grid);
52         }
53         bfs(row, col, grid, cost, done, count, distance + 1);
54         for (int i = 0; i < row1.size(); i++) {
55             done[row1.get(i)][col1.get(i)] = false;
56         }
57     }
58 
59     private void enqueue(Deque<Integer> row, Deque<Integer> col, int i, int j, boolean[][] done, int[][] grid) {
60         int down = i + 1;
61         int up = i - 1;
62         int left = j - 1;
63         int right = j + 1;
64         if (up >= 0 && !done[up][j] && grid[up][j] == 0) {
65             row.offer(up);
66             col.offer(j);
67             done[up][j] = true;
68         }
69         if (down < grid.length && !done[down][j] && grid[down][j] == 0) {
70             row.offer(down);
71             col.offer(j);
72             done[down][j] = true;
73         }
74         if (left >= 0 && !done[i][left] && grid[i][left] == 0) {
75             row.offer(i);
76             col.offer(left);
77             done[i][left] = true;
78         }
79         if (right < grid[0].length && !done[i][right] && grid[i][right] == 0) {
80             row.offer(i);
81             col.offer(right);
82             done[i][right] = true;
83         }
84     }
85 
86     private boolean isValid(int[][] count, int total) {
87         for (int[] aCount : count) {
88             for (int c : aCount) {
89                 if (c == total) {
90                     return true;
91                 }
92             }
93         }
94         return false;
95     }
96 }

 

posted on 2015-12-15 15:10  _icecream  阅读(739)  评论(0编辑  收藏  举报