Question
A group of two or more people wants to meet and minimize the total travel distance. You are given a 2D grid of values 0 or 1, where each 1 marks the home of someone in the group. The distance is calculated using Manhattan Distance, where distance(p1, p2) = |p2.x - p1.x| + |p2.y - p1.y|
.
For example, given three people living at (0,0)
, (0,4)
, and (2,2)
:
1 - 0 - 0 - 0 - 1 | | | | | 0 - 0 - 0 - 0 - 0 | | | | | 0 - 0 - 1 - 0 - 0
The point (0,2)
is an ideal meeting point, as the total travel distance of 2+2+2=6 is minimal. So return 6.
Hint:
- Try to solve it in one dimension first. How can this solution apply to the two dimension case?
Solution 1 -- Sort
根据曼哈顿距离的表达式,我们可以把这个问题转化为求每一维的最短距离。
总距离 = x上最短总距离 + y上最短总距离
并且,我们观察到,对于一个序列,如 [0,0,1,0,1,0,1,1,1,0,0,1]
当邮局选在median的位置时,距离和是最小的。
因此,这里我们遍历数组,得到home的x和y坐标值,然后分别对这两个list排序。再用双指针得到总的最短距离和。
Time complexity O(mn log(mn))
1 public class Solution { 2 public int minTotalDistance(int[][] grid) { 3 if (grid == null || grid.length < 1) { 4 return 0; 5 } 6 int m = grid.length, n = grid[0].length; 7 List<Integer> xList = new ArrayList<Integer>(); 8 List<Integer> yList = new ArrayList<Integer>(); 9 for (int i = 0; i < m; i++) { 10 for (int j = 0; j < n; j++) { 11 if (grid[i][j] == 1) { 12 xList.add(i); 13 yList.add(j); 14 } 15 } 16 } 17 return calcTotalDistance(xList) + calcTotalDistance(yList); 18 } 19 20 private int calcTotalDistance(List<Integer> list) { 21 if (list == null || list.size() < 2) { 22 return 0; 23 } 24 Collections.sort(list); 25 int len = list.size(); 26 int i = 0, j = len - 1; 27 int result = 0; 28 while (i < j) { 29 int left = list.get(i); 30 int right = list.get(j); 31 result += (right - left); 32 i++; 33 j--; 34 } 35 return result; 36 } 37 }
Solution 2 -- Without sorting
Discussion里有人给出了不用排序的方法。时间复杂度降低为O(mn)
因为双层循环遍历数组本身就是有次序性的。
1. 外层循环为遍历行,内层循环为遍历该行的每一个元素。
这样得到的是排序好的x的list
2. 外层循环为遍历列,内层循环为遍历该列的每一个元素。
这样得到的是排序好的y的list
1 public class Solution { 2 public int minTotalDistance(int[][] grid) { 3 if (grid == null || grid.length < 1) { 4 return 0; 5 } 6 int m = grid.length, n = grid[0].length; 7 List<Integer> xList = new ArrayList<Integer>(); 8 List<Integer> yList = new ArrayList<Integer>(); 9 for (int i = 0; i < m; i++) { 10 for (int j = 0; j < n; j++) { 11 if (grid[i][j] == 1) { 12 xList.add(i); 13 } 14 } 15 } 16 for (int j = 0; j < n; j++) { 17 for (int i = 0; i < m; i++) { 18 if (grid[i][j] == 1) { 19 yList.add(j); 20 } 21 } 22 } 23 24 return calcTotalDistance(xList) + calcTotalDistance(yList); 25 } 26 27 private int calcTotalDistance(List<Integer> list) { 28 if (list == null || list.size() < 2) { 29 return 0; 30 } 31 int len = list.size(); 32 int i = 0, j = len - 1; 33 int result = 0; 34 while (i < j) { 35 result += (list.get(j--) - list.get(i++)); 36 } 37 return result; 38 } 39 }