• [LeetCode] Shortest Distance from All Buildings Solution


    之前听朋友说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 }
  • 相关阅读:
    华为服务器内存插法
    关于公司内部域名称是否要和外部真实域名称对应的问题
    配置Office 365单点登录摘要
    配置Office 365单点登录过程中的一些注意事项
    AADC安装指南
    使用非Web方式从CA申请证书
    爬取某招聘网站的信息
    通过PowerShell启用AADC的密码同步功能
    Azure Active Directory Connect密码同步问题
    Python脚本配合Linux计划任务工作
  • 原文地址:https://www.cnblogs.com/icecreamdeqinw/p/5048375.html
Copyright © 2020-2023  润新知