• Java中数组自定义排序与优先级队列笔记


    今天在力扣每日一题中又遇到了需要取出数组前n个元素的题目,第一时间想到使用Arrays的sort排序,应该可以自定义比较器,或者使用大顶堆(优先级队列),但是一下没有写出来,还是去查了下资料,因此在这做个笔记以备无患。

    • Arrays的sort自定义比较器:Arrays.sort(数组,(a,b)->{return a-b(升序)/b-a(降序)});
      或者使用匿名类Arrays.sort(数组,new Comparator<>() { public int compare(int[] a,int[]b){return a-b(升序)/b-a(降序)});
      最后使用Arrays.copyOfRange(原数组, 起点, 终点)返回原数组的子数组即可。
      时间复杂度是nlogn,n为数组元素个数

    • 由于自定义比较器实现快排需要对数组里所有元素都进行排序,在这种题目中只需要取满足条件的前k个即可,因此可以使用固定k容量的大顶堆结构进行求解,采用的是PriorityQueue的api接口。
      首先定义一个优先级队列,定义其比较策略,这里采用的是逆序,因此堆顶元素为最不符合要求的,每次只要和堆顶元素对比即可。

    PriorityQueue<int[]> pq = new PriorityQueue<int[]>(new Comparator<int[]>() {
                public int compare(int[] array1, int[] array2) {
                    return array2[0] - array1[0];
                }
            });
    

    然后将数组前k项加入队列,完成初始化

    for (int i = 0; i < K; ++i) 
        pq.offer(new int[]{points[i][0] * points[i][0] + points[i][1] * points[i][1], i});
    

    最后后续项依次和堆顶进行比较,如果满足则抛出堆顶,将该项加入,PriorityQueue会按照比较策略重新生成堆顶。

    int n = points.length;
            for (int i = K; i < n; ++i) {
                int dist = points[i][0] * points[i][0] + points[i][1] * points[i][1];
                if (dist < pq.peek()[0]) {
                    pq.poll();
                    pq.offer(new int[]{dist, i});
                }
            }
    

    到最后剩下的即为所求的,再进行转换下数据结构,返回即可。时间复杂度是nlogk,k为所需要的元素,logk为每次重新插入元素的复杂度,因此比快排小一些。

    • 还有一种优化就是,依据快排的思想,对每次排序后左右的元素个数情况进行判断,从而得到前k个元素,这种代码编写比较考验基本功。
  • 相关阅读:
    每日一题20180325
    Linux下MySQL表名区分大小写
    CentOS删除编译安装的Python3
    HTTPS配置
    测试 js 方法运行时间(转)
    使用dbutils进行批处理
    oracle生成主键
    JDBC学习笔记(10)——调用函数&存储过程(转)
    easyui Draggable
    blob
  • 原文地址:https://www.cnblogs.com/alike/p/13948927.html
Copyright © 2020-2023  润新知