最靠近原点的2d坐标

时间:2012-07-28 16:06:45

标签: algorithm data-structures performance

我正在看下面的面试问题:

  

给定2d坐标,找到最接近的坐标   起源。提出用于存储点的数据结构和获得k点的方法。还要指出代码的复杂性。

我想到的解决方案是将2d点保存在数组中。对于前k个点,找到每个点与原点的距离并构建最大堆。对于剩余的点,计算距离原点的距离,比如dist。如果dist大于堆的最顶层元素,则将堆的最顶层元素更改为dist并运行heapify()过程。

这需要O(k)O((n-k)log k)过程构建堆和heapify(),因此总复杂度= O(n log k)

任何人都可以建议更好的数据结构和/或方法,效率可能更高吗?

修改

其他一些数据结构会在这里有用吗?

3 个答案:

答案 0 :(得分:3)

您要找的是partial sorting

我认为最好的方法是将所有内容放入未排序的数组中,然后使用修改后的就地快速排序,忽略索引完全高于或完全低于k的分区,并使用距原点的距离作为您的比较。

上面维基百科文章中的伪代码:

function quickfindFirstK(list, left, right, k)
     if right > left
         select pivotIndex between left and right
         pivotNewIndex := partition(list, left, right, pivotIndex)
         if pivotNewIndex > left + k  // new condition
             quickfindFirstK(list, left, pivotNewIndex-1, k)
         if pivotNewIndex < left + k
             quickfindFirstK(list, pivotNewIndex+1, right, k+left-pivotNewIndex-1)

执行后,这会在最先k个位置留下最小的k项,但不会按顺序排列。

答案 1 :(得分:1)

我会使用这个订单统计数据 请注意,我们使用修改后的SELECT,它使用距离原点的距离作为比较函数。

  • 将元素存储在数组A中,第一个元素为A[1],最后一个元素为A[n]
  • 运行SELECT(A,1,n,k)以找到距离原点最近的k元素。
  • 返回元素A[1..k]

SELECT分配输入的一个好处, 以便将最小的k-1元素留给A[k]

因此,将元素存储在数组中是O(n) 正在运行SELECTO(n) 返回请求的元素是O(1)

答案 2 :(得分:1)

我使用所谓的“部分排序”为您编写了一个简单的版本。 http://tzutalin.blogspot.sg/2017/02/interview-type-questions-minqueue.html

public static void main(String[] args) {
    Point[] points = new Point[7];
    points[0] = new Point(0, 0);
    points[1] = new Point(1, 7);
    points[2] = new Point(2, 2);
    points[3] = new Point(2, 2);
    points[4] = new Point(3, 2);
    points[5] = new Point(1, 4);
    points[6] = new Point(1, 1);
    int k = 3;
    qSelect(points, k - 1);
    for (int i = 0; i < k; i++) {
        System.out.println("" + points[i].x + "," + points[i].y);
    }
    // Output will be
    //        0,0
    //        1,1
    //        2,2
}

// in-place qselect and zero-based
static void qSelect(Point[] points, int k) {
    int l = 0;
    int h = points.length - 1;
    while (l <= h) {
        int partionInd = partition(l, h, points);
        if (partionInd == k) {
            return;
        } else if (partionInd < k) {
            l = partionInd + 1;
        } else {
            h = partionInd - 1;
        }
    }
}

static int partition(int l, int h, Point[] points) {
    // Random can be better
    // int p = l + new Random.nextInt(h - l + 1);
    int p = l + (h - l) / 2;
    int ind = l;
    swap(p, h, points);
    Point comparePoint = points[h];
    for (int i = l; i < h; i++) {
        if (points[i].getDistFromCenter() < comparePoint.getDistFromCenter()) {
            swap(i, ind, points);
            ind++;
        }
    }
    swap(ind, h, points);
    return ind;
}

static void swap(int i, int j, Point[] points) {
    Point temp = points[i];
    points[i] = points[j];
    points[j] = temp;
}