Build Post Office

Description

Given a 2D grid, each cell is either an house  1 or empty  0 (the number zero, one), find the place to build a post office, the distance that post office to all the house sum is smallest. Return the smallest distance. Return  -1 if it is not possible.
  • You can pass through house and empty.
  • You only build post office on an empty.
  • The distance between house and the post office is Manhattan distance

Example

Example 1:

Input:[[0,1,0,0],[1,0,1,1],[0,1,0,0]]
Output: 6
Explanation:
Placing a post office at (1,1), the distance that post office to all the house sum is smallest.

Example 2:
Input:[[0,1,0],[1,0,1],[0,1,0]]
Output: 4
Explanation:
Placing a post office at (1,1), the distance that post office to all the house sum is smallest.
思路:

方法一:

  • 由于题中所求两点间距离表示为d(i,j)=|xi-xj|+|yi-yj|,所以可以在x方向和y方向分别计算,然后求和即可,实现一维方向的计算即可。
  • 首先遍历网格,为1的方格,将其横纵坐标,即i和j分别存储,然后排序,方便接下来的查找计算。然后利用sumx和sumy前缀和,sumx代表起点到各个点的x方向距离和,sumy同理。
  • 再次遍历网格,当前处为0时,首先二分查找该方向i或j的位置,如果有多个相同的,寻找最右边的,即可,设为index。
  • 然后求和即可
  • sum.get(n) - sum.get(index + 1) - pos * (n - index - 1) + (index + 1) * pos - sum.get(index + 1);
  • sum.get(n) - sum.get(index + 1)计算出当前点右侧部分到起点的距离和
    • pos * (n - index - 1) 减去多余部分,因为之前是到起点的距离和,现在要求到当前点的距离和
  • (index + 1) * pos - sum.get(index + 1) 此处开始计算当前点左侧部分,index+1个当前点距离和减去index+1到起点的距离和,即为左侧部分的距离和。

方法二:

    • 处理前缀:
      prefixSum1记录数组 a 的前缀和,即:prefixSum1[i]=a[0]+a[1]+..+a[i].
      prefixSum2记录数组 prefixSum1 前缀和,prefixSum2即为前 i 个点到第 i 个点的代价和。
    • 处理后缀:
      prefixSum1记录数组 a 的后缀和,即:prefixSum1[i]=a[n-1]+a[n-2]+..+a[i].
      prefixSum2记录数组 prefixSum1 的后缀和,prefixSum2即为 i 之后的点到第 i 个点的代价和。
      public class Solution {
          /**
           * @param grid: a 2D grid
           * @return: An integer
           */
         public int shortestDistance(int[][] grid) {
              // Write your code here
              int n = grid.length;
              if (n == 0)
                  return -1;
      
              int m = grid[0].length;
              if (m == 0)
                  return -1;
      
              List<Integer> sumx = new ArrayList<Integer>();
              List<Integer> sumy = new ArrayList<Integer>();
              List<Integer> x = new ArrayList<Integer>();
              List<Integer> y = new ArrayList<Integer>();
      
              int result = Integer.MAX_VALUE;
              for (int i = 0; i < n; ++i)
                  for (int j = 0; j < m; ++j)
                      if (grid[i][j] == 1) {
                          x.add(i);
                          y.add(j);
                      }
              
              Collections.sort(x);
              Collections.sort(y);
      
              int total = x.size();
      
              sumx.add(0);
              sumy.add(0);
              for (int i = 1; i <= total; ++i) {
                  sumx.add(sumx.get(i-1) + x.get(i-1));
                  sumy.add(sumy.get(i-1) + y.get(i-1));
              }
      
              for (int i = 0; i < n; ++i)
                  for (int j = 0; j < m; ++j)
                      if (grid[i][j] == 0) {
                          int cost_x = get_cost(x, sumx, i, total);
                          int cost_y = get_cost(y, sumy, j, total);
                          if (cost_x + cost_y < result)
                              result = cost_x + cost_y;
                      }
      
              return result;
          }
      
          public int get_cost(List<Integer> x, List<Integer> sum, int pos, int n) {
              if (n == 0)
                  return 0;
              if (x.get(0) > pos)
                  return sum.get(n) - pos * n;
      
              int l = 0, r = n - 1;
              while (l + 1 < r) {
                  int mid = l + (r - l) / 2;
                  if (x.get(mid) <= pos)
                      l = mid;
                  else
                      r = mid - 1;
              }
              
              int index = 0;
              if (x.get(r) <= pos)
                  index = r;
              else
                  index = l;
              return sum.get(n) - sum.get(index + 1) - pos * (n - index - 1) + 
                     (index + 1) * pos - sum.get(index + 1);
          }
      }
      

        

猜你喜欢

转载自www.cnblogs.com/FLAGyuri/p/12078555.html
今日推荐