找到最近的有相同 X 或 Y 坐标的点

标签: 数组

难度: Easy

给你两个整数 x 和 y ,表示你在一个笛卡尔坐标系下的 (x, y) 处。同时,在同一个坐标系下给你一个数组 points ,其中 points[i] = [ai, bi] 表示在 (ai, bi) 处有一个点。当一个点与你所在的位置有相同的 x 坐标或者相同的 y 坐标时,我们称这个点是 有效的 。

请返回距离你当前位置 曼哈顿距离 最近的 有效 点的下标(下标从 0 开始)。如果有多个最近的有效点,请返回下标 最小 的一个。如果没有有效点,请返回 -1 。

两个点 (x1, y1) 和 (x2, y2) 之间的 曼哈顿距离 为 abs(x1 - x2) + abs(y1 - y2) 。

示例 1:

输入:x = 3, y = 4, points = [[1,2],[3,1],[2,4],[2,3],[4,4]]
输出:2
解释:所有点中,[3,1],[2,4] 和 [4,4] 是有效点。有效点中,[2,4] 和 [4,4] 距离你当前位置的曼哈顿距离最小,都为 1 。[2,4] 的下标最小,所以返回 2 。

示例 2:

输入:x = 3, y = 4, points = [[3,4]]
输出:0
提示:答案可以与你当前所在位置坐标相同。

示例 3:

输入:x = 3, y = 4, points = [[2,3]]
输出:-1
解释:没有 有效点。

提示:

  • 1 <= points.length <= 104
  • points[i].length == 2
  • 1 <= x, y, ai, bi <= 104

Submission

运行时间: 96 ms

内存: 18.2 MB

class Solution:
    def nearestValidPoint(self, x: int, y: int, points: List[List[int]]) -> int:
        index = -1
        minDistance = float("+inf")
        for i, point in enumerate(points):
            if self.isValid(x, y, point):
                distance = self.calculateDistance(x, y, point)
                if distance < minDistance:
                    minDistance = distance
                    index = i
        return index

    def isValid(self, x, y, point):
        return x == point[0] or y == point[1]

    def calculateDistance(self, x, y, point):
        return abs(x-point[0]) + abs(y-point[1])

Explain

这个题解首先初始化最小距离为无穷大和下标为-1。接着遍历每一个点,通过辅助函数isValid来判断点是否有效(即x坐标或y坐标与给定的x或y相同)。如果点是有效的,计算当前点与给定点的曼哈顿距离。如果这个距离小于当前记录的最小距离,则更新最小距离和对应的下标。最后,返回记录的下标。如果没有有效的点,返回-1。

时间复杂度: O(n)

空间复杂度: O(1)

# Definition for a point validation and distance calculation class

class Solution:
    def nearestValidPoint(self, x: int, y: int, points: List[List[int]]) -> int:
        index = -1  # 存储最近有效点的下标
        minDistance = float("+inf")  # 初始化最小距离为无限大
        for i, point in enumerate(points):  # 遍历所有点
            if self.isValid(x, y, point):  # 检查点是否有效
                distance = self.calculateDistance(x, y, point)  # 计算曼哈顿距离
                if distance < minDistance:  # 如果计算出的距离更小
                    minDistance = distance  # 更新最小距离
                    index = i  # 更新最近点的下标
        return index  # 返回最近有效点的下标,或者-1

    def isValid(self, x, y, point):
        return x == point[0] or y == point[1]  # 点有效的条件:x或y坐标相同

    def calculateDistance(self, x, y, point):
        return abs(x-point[0]) + abs(y-point[1])  # 计算曼哈顿距离

Explore

在题解中,当计算出的曼哈顿距离小于当前记录的最小距离时,会更新最小距离并记录当前的下标。如果后面的点也有相同的最小距离,不会更新下标,因为只有当新的距离严格小于已记录的最小距离时,才更新下标。这样确保了当多个点的距离相等时,返回的是第一个计算出的最小距离的点的下标。

isValid函数在当前的实现中是基于整数比较的,它假定x和y坐标都是整数。如果输入是非整数(例如浮点数),这个函数仍可以运行,但可能不符合题目的预期,因为坐标通常表示为整数。对于非常大的整数坐标,Python可以处理较大的整数,但在其他语言或系统中可能会遇到溢出问题。因此,isValid函数的实际适用性取决于具体的环境和输入范围的预期。

使用`float('+inf')`来表示无穷大在许多现代编程语言中是有效的,如Python、JavaScript和Java。但并非所有编程语言都支持这种表示方法,例如在C或C++中,通常使用其他方法如最大浮点数或特定的库函数。一个替代方法是使用已知的最大可能距离加一来初始化最小距离,例如在有明确坐标限制的情况下,或者使用系统或语言提供的最大数值常量。

曼哈顿距离是基于网格线上的点之间的距离,适合于城市街道等网格化的环境,其中你只能沿着网格线移动。在本题中,曼哈顿距离是合适的,因为我们查找与给定点有相同x或y坐标的点。相比之下,欧几里得距离测量的是点到点之间的直线距离,对于需要直线移动距离的场景更适合。使用曼哈顿距离的一个优点是计算上更简单,只涉及整数操作,而计算欧几里得距离则可能需要进行平方和开方运算,计算上更复杂。