数学,LeetCode 3102. 最小化曼哈顿距离

一、题目

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、原题链接

3102. 最小化曼哈顿距离


二、解题报告

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;
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

EQUINOX1

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值