LeetCode 296. Best Meeting Point(最佳见面点)
Posted jmspan
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了LeetCode 296. Best Meeting Point(最佳见面点)相关的知识,希望对你有一定的参考价值。
原题网址:https://leetcode.com/problems/best-meeting-point/
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?
曼哈顿距离有个特点:水平距离与垂直距离独立,因此分别计算水平的最佳点和垂直的最佳点,组合起来就是最佳的见面地点。
一维上的最佳地点,是坐标的中位数,这里有一个非常好的寻找中位数的算法,两面夹逼。
public class Solution
private int median(int[] nums)
int i=0, j=nums.length-1;
while (true)
while (i<j && nums[i]==0) i++;
while (i<j && nums[j]==0) j--;
if (i==j) break;
int min = Math.min(nums[i], nums[j]);
nums[i] -= min;
nums[j] -= min;
return i;
private int distance(int[] nums, int i)
int dist=0;
for(int a=0, left=0; a<i; a++)
left+=nums[a];
dist+=left;
for(int a=nums.length-1, right=0; a>i; a--)
right+=nums[a];
dist+=right;
return dist;
public int minTotalDistance(int[][] grid)
int[] v = new int[grid.length];
int[] h = new int[grid[0].length];
for(int i=0; i<grid.length; i++)
for(int j=0; j<grid[i].length; j++)
if (grid[i][j]==1)
v[i]++;
h[j]++;
return distance(h, median(h.clone())) + distance(v, median(v.clone()));
进一步优化:
public class Solution
public int minTotalDistance(int[][] grid)
int[] cols = new int[grid[0].length];
int[] rows = new int[grid.length];
for(int i=0; i<grid.length; i++)
for(int j=0; j<grid[i].length; j++)
if (grid[i][j]==1)
cols[j] ++;
rows[i] ++;
return minDist(cols) + minDist(rows);
private int minDist(int[] nums)
int dist = 0;
int left = 0, right = 0;
int i = 0, j = nums.length-1;
while (i<=j)
if (left <= right)
dist += left;
left += nums[i++];
else
dist += right;
right += nums[j--];
if (left<=right) dist+=left; else dist+=right;
return dist;
进一步优化:
public class Solution
public int minTotalDistance(int[][] grid)
if (grid == null || grid.length == 0 || grid[0].length == 0) return 0;
int[] h = new int[grid[0].length];
int[] v = new int[grid.length];
for(int i = 0; i < grid.length; i++)
for(int j = 0; j < grid[i].length; j++)
h[j] += grid[i][j];
v[i] += grid[i][j];
return distance(h) + distance(v);
private int distance(int[] nums)
if (nums.length <= 1) return 0;
int dist = 0;
int i = 0, j = nums.length - 1;
int di = nums[i], dj = nums[j];
while (i < j)
if (di <= dj)
dist += di;
di += nums[++i];
else
dist += dj;
dj += nums[--j];
return dist;
以上是关于LeetCode 296. Best Meeting Point(最佳见面点)的主要内容,如果未能解决你的问题,请参考以下文章
[LeetCode] Best Meeting Point 最佳开会地点
LeetCode Best Time to Buy and Sell Stock with Cooldown