LeetCode 973 最接近原点的K个点

发布于:2024-04-11 ⋅ 阅读:(139) ⋅ 点赞:(0)

题目信息

LeetoCode地址: . - 力扣(LeetCode)

题目理解

题意简单且直观,而且是很经典的考验快速排序以及堆排序的算法题,很考验基本功。

堆排序写法

对points数组原地建立小顶堆

并依次弹出第1个元素,重新调整堆顶元素,再弹出第1个。。。直到弹出前K个元素。

时间复杂度: O(nlogn)

额外空间复杂度:O(k)

class Solution {
    int[][] points;
    public int[][] kClosest(int[][] points, int k) {
        this.points = points;
        buildMinHeap(points, points.length);
        int[][] res = new int[k][2];
        int lastIndex =points.length-1;
        for (int i = 0; i<k; i++) {
            res[i] = points[0];
            swap(0, lastIndex--);
            minHeapify(0, lastIndex+1);
        }
        return res;
    }
    public void buildMinHeap(int[][] points, int length) {
        for (int i = points.length/2; i>=0; i--) {
            minHeapify(i, length);
        }
    }
    public void minHeapify(int i, int length) {
        int l = i*2+1, r = i*2+2;
        int min = i;
        int minLength = points[i][0]*points[i][0] + points[i][1]*points[i][1];
        int lMinLength = l < length ? points[l][0]*points[l][0] +points[l][1] * points[l][1] : Integer.MAX_VALUE;
        int rMinLength = r < length ? points[r][0]*points[r][0] +points[r][1] * points[r][1] : Integer.MAX_VALUE;
        if (lMinLength < minLength) {
            min = l;
            minLength = lMinLength;
        }
        if (rMinLength < minLength) {
            min = r;
        }
        if (i != min) {
            swap(i, min);
            minHeapify(min, length);
        }
    }
    void swap(int a, int b) {
        int[] tmp = points[a];
        points[a] = points[b];
        points[b] = tmp;
    }
}

快速排序写法

普通的写法是直接对整个数组排序,然后取前k个元素,然而这不是最高效的。

由于我们仅需要前k个元素,而且不关注顺序,因此可以省略到k之后元素的顺序。

假如我们当前左右边界分别是l和r,在快排中间步骤中,确认了j位置元素的值后,如果发现k <= j, 则无需再关注j到r之间元素的排序结果;

类似的,假如k > j, 那我们也无需再关注l到j之间的元素,因为我们已经确认了他们必定会出现在最终结果集中。

时间复杂度:O(n), 由于我们没有进行任何多余元素的排序动作。

额外空间复杂度:O(1), 我们是在原地进行排序,没有使用额外空间。

    int k;
    int[][] points;
    public int[][] kClosest(int[][] points, int k) {
        this.k = k;
        this.points = points;
        quickSort(0, points.length-1);   
        return Arrays.copyOfRange(points, 0, k);
    }
    public void quickSort(int l, int r) {
        if (l == r) {
            return;
        }
        int i = l-1, j = r+1;
        int[] mid = points[l+ (r-l)/2];
        while (i < j) {
            while (compare(mid, points[++i]));
            while (compare(points[--j], mid));
            if (i < j) {
                swap(i, j);
            }
        }
        if (j >= k) {
            quickSort(l, j);
        } else if (k >= j+1) {
            quickSort(j+1, r);
        }
    }
    boolean compare(int[] a, int[] b) {
        return (a[0]*a[0] + a[1]*a[1]) > (b[0]*b[0] + b[1]*b[1]);
    }
    void swap(int a, int b) {
        int[] tmp = points[a];
        points[a] = points[b];
        points[b] = tmp;
    }


网站公告

今日签到

点亮在社区的每一天
去签到