以leetcode973问为例
题目描述
我们有一个由平面上的点组成的列表 points。需要从中找出 K 个距离原点 (0, 0) 最近的点。
(这里,平面上两点之间的距离是欧几里德距离。)
你可以按任何顺序返回答案。除了点坐标的顺序之外,答案确保是唯一的。
示例 1:
输入:points = [[1,3],[-2,2]], K = 1
输出:[[-2,2]]
解释:
(1, 3) 和原点之间的距离为 sqrt(10),
(-2, 2) 和原点之间的距离为 sqrt(8),
由于 sqrt(8) < sqrt(10),(-2, 2) 离原点更近。
我们只需要距离原点最近的 K = 1 个点,所以答案就是 [[-2,2]]。
示例 2:
输入:points = [[3,3],[5,-1],[-2,4]], K = 2
输出:[[3,3],[-2,4]]
(答案 [[-2,4],[3,3]] 也会被接受。)
提示:
1 <= K <= points.length <= 10000
-10000 < points[i][0] < 10000
-10000 < points[i][1] < 10000
解法
快排
class Solution {
public int[][] kClosest(int[][] points, int K) {
adjustedQuickSort(points, 0, points.length - 1, K);
return Arrays.copyOfRange(points, 0, K);
}
private void adjustedQuickSort(int[][] A, int left, int right, int K)
{
if (right - left + 1 > 3)
{
int pivot = medianThree(A, left, right);
int low = left, high = right - 1;
while (true)
{
while (euDistance(A[++low]) < pivot);
while (euDistance(A[--high]) > pivot);
if (low < high)
Swap(A, low, high);
else
break;
}
Swap(A, low, right - 1);
int kMinLen = low - left + 1;
if (kMinLen < K)
adjustedQuickSort(A,low + 1, right, K - kMinLen);
else if (kMinLen > K)
adjustedQuickSort(A, left, low - 1, K);
}
else
{
insertionSort(A, left, right);
}
}
private void insertionSort(int[][] A, int left, int right)
{
for (int P = left + 1; P <= right; P++)
{
int[] temp = A[P];
int i = P;
for (; i > 0 && euDistance(temp) < euDistance(A[i - 1]); i--)
{
A[i] = A[i -1];
}
A[i] = temp;
}
}
private int euDistance(int[] point)
{
int distance = point[0]*point[0] + point[1] * point[1];
return distance;
}
private void Swap(int[][] A, int a, int b)
{
int[] temp = A[a];
A[a] = A[b];
A[b] = temp;
}
private int medianThree(int[][] A, int left, int right)
{
int center = (left + right) >>> 1;
if (euDistance(A[left]) > euDistance(A[center]))
Swap(A, left, center);
if (euDistance(A[left]) > euDistance(A[right]))
Swap(A, left, right);
if (euDistance(A[center]) > euDistance(A[right]))
Swap(A, center, right);
Swap(A, center, right - 1);
return euDistance(A[right - 1]);
}
}