【问题标题】:How can we find K closest points to the origin, and sort based on x-coordinates when there's equal distances to consider?当需要考虑相等的距离时,我们如何找到距离原点最近的 K 个点,并根据 x 坐标进行排序?
【发布时间】:2022-01-26 02:51:34
【问题描述】:

给定一堆 (x, y) 坐标,我们需要找到离原点最近的 K 个点。当我们找到一些与原点距离相等的点并且我们需要考虑它们之间的一些时,我们取 x 坐标最小的点。如果两个 x 坐标相同(这意味着 2 个点相等) - 我们取其中任何一个。

例如 - 我们得到 (1,1), (-2,3), (2, 3) 和 K = 2

所以,答案是 (1,1) 和 (-2, 3)。

我的方法是 - 在原始点列表中生成距离与位置之间的地图。然后得到一系列距离并对其进行排序。然后我们获取新排序数组中的每个距离并从地图中提取所有键(因此是原始数组中的位置),如果它们大于 1 并且我们还没有达到 K -> 我们检查 x 坐标并将其添加到结果中。但我无法正确实现,而且我认为这不是最有效的方法。

【问题讨论】:

    标签: algorithm sorting hashmap heap


    【解决方案1】:

    您无需查找所有距离并对其进行排序。保持最多为K 长度的最大堆就足够了。您可以将x 坐标作为堆排序算法的第二个参数。

    这里有一个 Python 解决方案,您可以将其视为几乎是伪代码:

    import heapq
    
    hp = []
    for x, y in coordinates:
      dist = x**2 + y**2
      heapq.heappush(hp, (-dist, -x, y))
      if len(hp) >= K:
        heapq.heappop(hp)
    
    res = [(-x, y) for d, x, y in hp]
    

    请注意,当len(hp) >= k 时,我们可以使用heapq.heappushpop。这稍微更有效,但由于它是特定于实现的,所以它并不重要。

    这是我们的工作:

    1. 将 (dist, x, y) 的元组推送到堆上。请注意,由于 python 的默认堆实现是最小堆,我们需要将距离和 x 坐标取反,以便较大的距离和 x 坐标位于堆的顶部。
    2. 只要堆的长度 >= K,我们就会弹出一个。这确保了首先弹出距离最长的坐标(因为它是一个最小堆并且我们正在否定距离)。它还确保在出现平局的情况下,首先弹出较大的 x 坐标。
    3. 最后,我们从堆中提取坐标,确保将 x 坐标取反。

    这个算法的时间复杂度是O(n * log k),其中n是坐标列表的长度,k是我们想要的坐标数。

    空间复杂度为k

    【讨论】:

    • 好的,对于 1. 我们可以使用最大堆吗,对于 java,可以选择提供一个标志来使其成为最大堆结构。 2. 发生碰撞时,您能否提供一些有关此堆属性的文档。 java有没有这样的东西? @user1984
    • Java 具有 PriorityQueue 数据结构,其作用与 python 堆相同。对于您的问题,您需要在构造时提供自定义Comparator。创建一个包含距离和 x y 坐标的类。在您的 Comparator 中,请考虑距离的关系如何与 x 坐标断开。其余的,如果有一个平局并且你没有在 Comparator 中打破它,Java 将任意将一个元素放在另一个元素之前。
    • 好的,对于python,你能在发生碰撞时提供一些文档吗?它从 dist 到 x 再到 y? @user1984 谢谢。
    【解决方案2】:

    另一种方法是Balltree。它可以query 最接近的K 点。我先生成10K个随机点,整数。

    import numpy as np
    from sklearn.neighbors import BallTree
    
    points = np.floor(np.random.normal(size=(10000,2), loc=(25,25), scale=(16,16)))
    
    K = 12
    

    创建一棵树,并查询它以找到最接近 K 的点,到 (0,0)

    tree = BallTree(points, leaf_size=10, metric='euclidean')
    
    distances, indici = tree.query( np.array([[0,0]]), k=K,return_distance=True)
    

    创建一个(distance, point) 元组,以便以后可以随意排序。

    close_points_as_list = [ (x,y) for (x,y) in points[indici].tolist()[0] ]
    distances_as_list = distances.tolist()[0]
    
    distances_points_tuples = list(zip(distances_as_list, close_points_as_list))
    

    对于列表中的pdistances_points_tuplesp[0] 是到(0,0) 的距离,p[1][0] 是 x,p[1][1] 是 y。

    我不确定“最小”x 是什么。注意我使用 x 的np.abs() 来定义第二级排序。

    sorted_points = sorted(distances_points_tuples, key=lambda x: (x[0], np.abs(x[1][0])) )
    

    import pprint
    
    pprint.pprint(sorted_points)
    

    会给

    [(0.0, (0.0, 0.0)),
     (1.4142135623730951, (1.0, -1.0)),
     (1.4142135623730951, (-1.0, -1.0)),
     (1.4142135623730951, (-1.0, 1.0)),
     (1.4142135623730951, (-1.0, 1.0)),
     (2.0, (0.0, -2.0)),
     (2.0, (0.0, 2.0)),
     (2.23606797749979, (-1.0, -2.0)),
     (2.23606797749979, (2.0, 1.0)),
     (2.23606797749979, (-2.0, 1.0)),
     (2.23606797749979, (-2.0, -1.0)),
     (2.23606797749979, (-2.0, 1.0))]
    

    【讨论】:

      猜你喜欢
      • 2017-06-21
      • 1970-01-01
      • 2014-09-07
      • 2018-06-16
      • 2019-06-29
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-07-09
      相关资源
      最近更新 更多