一、题目
1、题目描述
给你一个下标从 0 开始的数组
points
,它表示二维平面上一些点的整数坐标,其中points[i] = [xi, yi]
。两点之间的距离定义为它们的
曼哈顿距离
。请你恰好移除一个点,返回移除后任意两点之间的 最大 距离可能的 最小 值。
2、接口描述
python3
class Solution:
def minimumDistance(self, points: List[List[int]]) -> int:
cpp
class Solution {
public:
int minimumDistance(vector<vector<int>>& points) {
}
};
C#
public class Solution {
public int MinimumDistance(int[][] points) {
}
}
3、原题链接
二、解题报告
1、思路分析
有的做法是将曼哈顿距离转化为切比雪夫距离的,个人还是比较喜欢下面这种做法,也是当初周赛的时候写的做法:
对于任意两个坐标(a, b), (c, d)
不妨设其曼哈顿距离为 a - c + b - c = a + b - c - d
我们发现坐标(a, b)和(c, d)曼哈顿距离中每个维度的系数相反
而对于二维坐标的系数无非就(-1, -1), (-1, 1), (1, -1), (1, 1)4种情况
每种情况下的最大值和最小值之差 的 最大值就是我们的最大曼哈顿距离
该做法可以推广到n维坐标,时间复杂度为(2^N * M)M为坐标个数
2、复杂度
时间复杂度: O(4n)空间复杂度:O(n)
3、代码详解
python3
fmax = lambda x, y: x if x > y else y
fmin = lambda x, y: x if x < y else y
class Solution:
def minimumDistance(self, points: List[List[int]]) -> int:
n = len(points)
res = 10**9
buf = []
tt = 0
for a, b in (1, 1), (-1, -1), (1, -1), (-1, 1):
ma, mi = -10**9, 10**9
mai = mii = -1
for i, (x, y) in enumerate(points):
t = a * x + b * y
if t > ma:
ma, mai = t, i
if t < mi:
mi, mii = t, i
tt = fmax(tt, ma - mi)
if ma - mi > tt:
tt = ma - mi
buf = [mai, mii]
elif ma - mi == tt:
buf.extend([mai, mii])
for i in buf:
tt = 0
for a, b in (1, 1), (-1, -1), (1, -1), (-1, 1):
ma, mi = -10**9, 10**9
for j, (x, y) in enumerate(points):
if j == i:
continue
t = a * x + b * y
ma = fmax(ma, t)
mi = fmin(mi, t)
tt = fmax(tt, ma - mi)
res = fmin(res, tt)
return res
cpp
class Solution {
public:
int minimumDistance(vector<vector<int>>& points) {
int n = points.size(), ret = 1e9, s = 0;
vector<int> buf;
for(int i = 0, ed = (1 << 2); i < ed; i++){
int ma = -1e9, mi = 1e9, mai, mii;
for(int j = 0, s; j < n; j++){
int sum = 0;
for(int k = 0; k < 2; k++)
if(i >> k & 1) sum -= points[j][k];
else sum += points[j][k];
if(sum > ma) ma = sum, mai = j;
if(sum < mi) mi = sum, mii = j;
}
if(ma - mi > s) s = ma - mi, buf = { mai, mii };
else if(ma - mi == s) buf.insert(buf.end(), { mai, mii } );
}
for(auto x : buf){
s = 0;
for(int i = 0, ed = (1 << 2); i < ed; i++){
int ma = -1e9, mi = 1e9, mai, mii;
for(int j = 0, s; j < n; j++){
if(j == x) continue;
int sum = 0;
for(int k = 0; k < 2; k++){
if(i >> k & 1) sum -= points[j][k];
else sum += points[j][k];}
if(sum > ma) ma = sum, mai = j;
if(sum < mi) mi = sum, mii = j;
}
if(ma - mi > s) s = ma - mi;
}
ret = min(ret , s);
}
return ret;
}
};
C#
using System;
using System.Collections.Generic;
using System.Linq;
public class Solution
{
public int MinimumDistance(IList<IList<int>> points)
{
int n = points.Count;
int res = (int)Math.Pow(10, 9);
List<int> buf = new List<int>();
int tt = 0;
Func<int, int, int> fmax = (x, y) => x > y ? x : y;
Func<int, int, int> fmin = (x, y) => x < y ? x : y;
var d = new List<(int, int)> { (1, 1), (-1, -1), (1, -1), (-1, 1) };
foreach (var (a, b) in d)
{
int ma = int.MinValue, mi = int.MaxValue;
int mai = -1, mii = -1;
for (int i = 0; i < points.Count; i++)
{
int x = points[i][0];
int y = points[i][1];
int t = a * x + b * y;
if (t > ma) {
ma = t;
mai = i;
}
if (t < mi) {
mi = t;
mii = i;
}
}
tt = fmax(tt, ma - mi);
if (ma - mi > tt)
{
tt = ma - mi;
buf = new List<int> { mai, mii };
}
else if (ma - mi == tt)
{
buf.AddRange(new List<int> { mai, mii });
}
}
foreach (int i in buf)
{
tt = 0;
foreach (var (a, b) in d)
{
int ma = int.MinValue, mi = int.MaxValue;
for (int j = 0; j < points.Count; j++)
{
if (j == i) continue;
int x = points[j][0];
int y = points[j][1];
int t = a * x + b * y;
ma = fmax(ma, t);
mi = fmin(mi, t);
}
tt = fmax(tt, ma - mi);
}
res = fmin(res, tt);
}
return res;
}
}