力扣刷题之3102.最小化曼哈顿距离

 题干要求:

给你一个下标从 0 开始的数组 points ,它表示二维平面上一些点的整数坐标,其中 points[i] = [xi, yi] 。

两点之间的距离定义为它们的曼哈顿距离。

请你恰好移除一个点,返回移除后任意两点之间的 最大 距离可能的 最小 值。

示例 1:

输入:points = [[3,10],[5,15],[10,2],[4,4]]
输出:12
解释:移除每个点后的最大距离如下所示:
- 移除第 0 个点后,最大距离在点 (5, 15) 和 (10, 2) 之间,为 |5 - 10| + |15 - 2| = 18 。
- 移除第 1 个点后,最大距离在点 (3, 10) 和 (10, 2) 之间,为 |3 - 10| + |10 - 2| = 15 。
- 移除第 2 个点后,最大距离在点 (5, 15) 和 (4, 4) 之间,为 |5 - 4| + |15 - 4| = 12 。
- 移除第 3 个点后,最大距离在点 (5, 15) 和 (10, 2) 之间的,为 |5 - 10| + |15 - 2| = 18 。
在恰好移除一个点后,任意两点之间的最大距离可能的最小值是 12 。

示例 2:

输入:points = [[1,1],[1,1],[1,1]]
输出:0
解释:移除任一点后,任意两点之间的最大距离都是 0 。

提示:

  • 3 <= points.length <= 105
  • points[i].length == 2
  • 1 <= points[i][0], points[i][1] <= 108

题干分析: 

        首先我们需要对该题干进行简单的理解:首先给定了曼哈顿距离的相关概念:给你一个下标从 0 开始的数组 points ,它表示二维平面上一些点的整数坐标,其中 points[i] = [xi, yi] 。以及通过后面的示例我么可以得出曼哈顿距离的求解公式为两个点的横坐标和纵坐标差值的绝对值。

        而“请你恰好移除一个点,返回移除后任意两点之间的 最大 距离可能的 最小 值。”这句话的意思则是指已知在一个二维平面中存在若干点,通过敲好移动一个点,计算剩余点的最大曼哈顿距离,最后返回这个距离的最小可能值。

         所以根据上面的分析我们可以得到解决这道题的相关步骤:

1.移除一个点:假设移除一个点

2.计算剩余点中的最大距离:在剩下的点中找到任意两点之间的最大曼哈顿距离。

3.找出最小的最大距离:对于每一个可能被移除的点,找到移除该点之后剩余点中的最大距离,最后找出这些最大距离中的最小值。

          这里我们还可以通过题目所提供的示例一进行进一步的理解:

已知输入:points = [[3,10],[5,15],[10,2],[4,4]]
       输出:12

解决过程:

  • 如果移除第一个点 [3, 10],剩余点为 [[5, 15], [10, 2], [4, 4]]。最大曼哈顿距离是 |5-10| + |15-2| = 18
  • 如果移除第二个点 [5, 15],剩余点为 [[3, 10], [10, 2], [4, 4]]。最大曼哈顿距离是 |3-10| + |10-2| = 15
  • 如果移除第三个点 [10, 2],剩余点为 [[3, 10], [5, 15], [4, 4]]。最大曼哈顿距离是 |5-4| + |15-4| = 12
  • 如果移除第四个点 [4, 4],剩余点为 [[3, 10], [5, 15], [10, 2]]。最大曼哈顿距离是 |5-10| + |15-2| = 18

而在所有上述例子中 最短的距离是12,因此我们选择移除第三个点,最后得出的最大曼哈顿距离是12。

根据以上题干分析编写代码:

第一步:定义一个函数用于计算两个点之间的曼哈顿距离:
int manhattanDistance(int* p1, int* p2) {
    return abs(p1[0] - p2[0]) + abs(p1[1] - p2[1]);
}
第二步:定义一个方法用于计算移除一个点后最大曼哈顿距离的最小值

        值得注意的是这里的设计思路是:

1.遍历所有的点用于计算x+y和x-y,并更新最大数和最小值:

for (int i = 0; i < pointsSize; i++) {
    int xPlusY = points[i][0] + points[i][1]; // 计算 x+y
    int xMinusY = points[i][0] - points[i][1]; // 计算 x-y
    // 比较计算所得的 x+y 和 x-y 与所记录的 x+y 和 x-y 的最大值和最小值,若更大或更小则更新数值
    if (xPlusY > maxXPlusY) maxXPlusY = xPlusY; // 更新 x+y 的最大值
    if (xPlusY < minXPlusY) minXPlusY = xPlusY; // 更新 x+y 的最小值
    if (xMinusY > maxXMinusY) maxXMinusY = xMinusY; // 更新 x-y 的最大值
    if (xMinusY < minXMinusY) minXMinusY = xMinusY; // 更新 x-y 的最小值
}

2.记录移除一个点后最大距离的最小值: 

int minMaxDist = INT_MAX; // 记录移除一个点后最大距离的最小值

3.定义若干假设来遍历每一个点假设一出它:

if (xPlusY == maxXPlusY) {
    tempMaxXPlusY = INT_MIN;
    for (int j = 0; j < pointsSize; j++) {
        if (j != i) {
            int val = points[j][0] + points[j][1];
            if (val > tempMaxXPlusY) tempMaxXPlusY = val;
        }
    }
}

if (xPlusY == minXPlusY) {
    tempMinXPlusY = INT_MAX;
    for (int j = 0; j < pointsSize; j++) {
        if (j != i) {
            int val = points[j][0] + points[j][1];
            if (val < tempMinXPlusY) tempMinXPlusY = val;
        }
    }
}

if (xMinusY == maxXMinusY) {
    tempMaxXMinusY = INT_MIN;
    for (int j = 0; j < pointsSize; j++) {
        if (j != i) {
            int val = points[j][0] - points[j][1];
            if (val > tempMaxXMinusY) tempMaxXMinusY = val;
        }
    }
}

if (xMinusY == minXMinusY) {
    tempMinXMinusY = INT_MAX;
    for (int j = 0; j < pointsSize; j++) {
        if (j != i) {
            int val = points[j][0] - points[j][1];
            if (val < tempMinXMinusY) tempMinXMinusY = val;
        }
    }
}

以上代码的设计思路:

1.假设移除一个点后,重新计算剩余点中的极值:

  • xPlusY == maxXPlusY 表示当前点的 x + y 是所有点中最大的值。
  • xPlusY == minXPlusY 表示当前点的 x + y 是所有点中最小的值。
  • xMinusY == maxXMinusY 表示当前点的 x - y 是所有点中最大的值。
  • xMinusY == minXMinusY 表示当前点的 x - y 是所有点中最小的值。

2.移除点后重新计算剩余点的极值: 

  • 如果当前点的 x + y 是最大值 maxXPlusY,则需要重新计算剩余点中的 x + y 的最大值 tempMaxXPlusY
  • 如果当前点的 x + y 是最小值 minXPlusY,则需要重新计算剩余点中的 x + y 的最小值 tempMinXPlusY
  • 如果当前点的 x - y 是最大值 maxXMinusY,则需要重新计算剩余点中的 x - y 的最大值 tempMaxXMinusY
  • 如果当前点的 x - y 是最小值 minXMinusY,则需要重新计算剩余点中的 x - y 的最小值 tempMinXMinusY

4. 计算移除点后的最大曼哈顿距离:

// 计算移除点后的最大曼哈顿距离
int maxDistAfterRemoval = fmax(tempMaxXPlusY - tempMinXPlusY, tempMaxXMinusY - tempMinXMinusY);

5.记录每次移除后的最大距离的最小值:

// 记录每次移除后的最大距离的最小值
minMaxDist = fmin(minMaxDist, maxDistAfterRemoval);

6.返回结果:

return minMaxDist; // 返回移除一个点后的最小最大距离
最后定义一个测试函数用来测试代码编写是否符合需求: 
// 测试函数
int main() {
    int pointsArray[][2] = { {3, 10}, {5, 15}, {10, 2}, {4, 4} };
    int* points[4];
    for (int i = 0; i < 4; ++i) {
        points[i] = pointsArray[i];
    }
    int pointsColSize[] = { 2, 2, 2, 2 };

    int result = minimumDistance(points, 4, pointsColSize);
    printf("移除一个点后的最小最大距离是:%d\n", result);

    return 0;
}
测试结果:

       已知题干最后仅需要编写关键函数即可,因此在力扣代码编写minimumDistance函数即可。相关的运行结果:

  • 29
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值