leetcode
leetcode 251 ~ 300
最佳的碰头地点

最佳的碰头地点

难度:

标签:

题目描述

代码结果

运行时间: 36 ms, 内存: 18.3 MB


/*
 * Leetcode 题目:最佳的碰头地点
 * 题目思路:
 * 1. 给定一个二维的网格,网格中的每一个格子表示一个位置。
 * 2. 多个人分别位于不同的格子中,找出一个位置使得这些人到这个位置的总距离最短。
 * 3. 使用曼哈顿距离计算:曼哈顿距离是两个点在标准坐标系上的绝对轴距总和。
 * 4. 思路是分别找出横坐标和纵坐标的中位数,这样总距离最短。
 */
 
import java.util.*;
import java.util.stream.*;
 
public class BestMeetingPointStream {
    public int minTotalDistance(int[][] grid) {
        List<Integer> rows = IntStream.range(0, grid.length)
            .boxed()
            .flatMap(i -> IntStream.range(0, grid[0].length)
                .filter(j -> grid[i][j] == 1)
                .mapToObj(j -> i))
            .sorted()
            .collect(Collectors.toList());
 
        List<Integer> cols = IntStream.range(0, grid[0].length)
            .boxed()
            .flatMap(j -> IntStream.range(0, grid.length)
                .filter(i -> grid[i][j] == 1)
                .mapToObj(i -> j))
            .sorted()
            .collect(Collectors.toList());
 
        int medianRow = rows.get(rows.size() / 2);
        int medianCol = cols.get(cols.size() / 2);
 
        int totalDistance = rows.stream().mapToInt(row -> Math.abs(row - medianRow)).sum()
            + cols.stream().mapToInt(col -> Math.abs(col - medianCol)).sum();
 
        return totalDistance;
    }
}
 

解释

方法:

这个题解的思路是利用中位数的性质来找到最佳的碰头地点。具体步骤如下: 1. 找出所有朋友的家的坐标,并将x坐标和y坐标分别存储在两个列表中。 2. 分别计算x坐标列表和y坐标列表的中位数,作为最佳碰头地点的坐标。 3. 计算所有朋友的家到最佳碰头地点的曼哈顿距离之和,即为最小的总距离。

时间复杂度:

O(mn log(mn))

空间复杂度:

O(mn)

代码细节讲解

🦆
为什么在计算中位数时,如果列表长度是偶数,你选择了返回下中位数而不是平均值?这对最终结果有什么影响?
在计算中位数时选择返回下中位数(较小的中位数)而不是平均值,是因为在求解最小曼哈顿距离的问题中,中位数的位置确保了所有点到该点的距离之和最小。选择下中位数或上中位数对最终的总距离计算影响不大,因为在中位数附近的任何一个整数点,其总曼哈顿距离都非常接近。具体到选择下中位数,这是一个常见的约定,简化了实现,尤其是在整数索引的数组中更为直观。
🦆
这个解法中,你提到了使用曼哈顿距离,能否解释为什么曼哈顿距离在这个问题中是适合的而不是欧几里得距离?
曼哈顿距离是在格点系统(如城市街区)中,沿着格点线测量的距离,适合于网格状结构的地图上的距离计算。在本问题中,朋友的家和碰头点都是在一个网格上,且通常只能沿格线(即水平或垂直方向)移动。相比之下,欧几里得距离是直线距离,适用于可以自由移动的空间,不适合本题的格点限制。因此,对于网格布局,曼哈顿距离更能准确反映从一点到另一点的实际移动距离。
🦆
在计算中位数时,你对x坐标和y坐标的列表进行了排序。这种排序是否会影响算法的性能,尤其是当朋友的数量非常多时?
排序是计算中位数的一个关键步骤,其时间复杂度为O(n log n)。当朋友的数量非常多时,排序的操作确实会对性能有所影响。但是,这种影响是必要的,因为只有通过排序才能正确确定中位数的位置,从而计算出最小的曼哈顿距离。若考虑性能优化,可以探索使用线性时间的选择算法(如快速选择算法)来找中位数,以改善在极大数据量时的性能表现。
🦆
在处理边界条件,例如所有朋友的家都位于网格的同一行或同一列时,中位数的计算方法是否还适用?
即使所有朋友的家位于网格的同一行或同一列,中位数的计算方法仍然适用。在这种情况下,中位数仍会是该行或该列的中心点,从而确保了计算出的曼哈顿距离是最小的。因此,中位数方法在处理这类边界条件时是有效的,可以正确地减少到碰头地点的总移动距离。

相关问题

离建筑物最近的距离

离建筑物最近的距离

最小操作次数使数组元素相等 II

给你一个长度为 n 的整数数组 nums ,返回使所有数组元素相等需要的最小操作数。

在一次操作中,你可以使数组中的一个元素加 1 或者减 1

 

示例 1:

输入:nums = [1,2,3]
输出:2
解释:
只需要两次操作(每次操作指南使一个元素加 1 或减 1):
[1,2,3]  =>  [2,2,3]  =>  [2,2,2]

示例 2:

输入:nums = [1,10,2,9]
输出:16

 

提示:

  • n == nums.length
  • 1 <= nums.length <= 105
  • -109 <= nums[i] <= 109