topK问题记录

以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]);
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值