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.
Ideas:
method one:
- Since the problem as required between two points represented as the distance d (i, j) = | xi-xj | + | yi-yj |, can be calculated separately in x and y directions, and then summed to achieve a one-dimensional direction can be calculated.
- First traverse grid squares is 1, the horizontal and vertical coordinates thereof, i.e., i and j are stored and sorted to find the following easy calculation. And then use sumx Sumy prefix and, on behalf of the origin to x sumx direction and distance, sumy empathy each point.
- Again traversing the grid, currently at 0, the position of the first binary search direction i or j, and if there is more of the same, look for the far right, you can, set index.
- And then summed to
- 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) to calculate the current distance from the start point to the right side portion and
-
- pos * (n - index - 1) minus the excess part, because prior to the start point and the distance is now required to the current point and the distance
- (Index + 1) * pos - start to the left portion of the current point sum.get (index + 1) Here, index + 1 th current point distance minus the distance index + 1 and the starting point, namely a left portion and distance.
Method Two:
- Processing prefix:
prefixSum1 array a prefix and recording, namely:. PrefixSum1 [i] = a [0] + a [. 1] + .. + a [i]
prefixSum2 prefixSum1 prefix and an array of records, prefixSum2 is the i-th point before the cost to the i-th point and. - Processing Suffix:
prefixSum1 array of records and a suffix, namely:. PrefixSum1 [I] = a [n--. 1] + a [2-n-] + .. + a [I]
prefixSum2 prefixSum1 suffix array and recorded, prefixSum2 i.e. i is a point after the cost to the i-th point and.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); } }