我正在看下面的面试问题:
给定2d坐标,找到最接近的坐标 起源。提出用于存储点的数据结构和获得k点的方法。还要指出代码的复杂性。
我想到的解决方案是将2d点保存在数组中。对于前k个点,找到每个点与原点的距离并构建最大堆。对于剩余的点,计算距离原点的距离,比如dist。如果dist大于堆的最顶层元素,则将堆的最顶层元素更改为dist并运行heapify()
过程。
这需要O(k)
为O((n-k)log k)
过程构建堆和heapify()
,因此总复杂度= O(n log k)
。
任何人都可以建议更好的数据结构和/或方法,效率可能更高吗?
修改
其他一些数据结构会在这里有用吗?
答案 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)
正在运行SELECT
是O(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;
}