优先队列 PriorityQueue

时间:2019-02-16
本文章向大家介绍优先队列 PriorityQueue,主要包括优先队列 PriorityQueue使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。

1 PriorityQueue 实现方式

1.1 时间复杂度

2 返回数据流中第 K 大元素

https://leetcode.com/problems/kth-largest-element-in-a-stream/

  • 最大的值,保存前 K 个,每次来的新的值,只要比保存的 K 个值的最小值大,则剔除原来 K 个值得最小值;
class KthLargest {

    private PriorityQueue<Integer> q;
    private int k;
    
    public KthLargest(int k, int[] nums) {
        this.k = k;
        q = new PriorityQueue<>(k);

        for (int num : nums) {
            add(num);
        }
    }
    
    public int add(int val) {
        if (q.size() < k) {
            q.offer(val);
        } else if (q.peek() < val) {
            q.poll();
            q.offer(val);
        }

        return q.peek();
    }
}

3 返回滑动窗口的最大值

  • 思路1 : Max Heap
1. 维护 heap , 时间复杂度 O (logK)
2. 取最大值:时间复杂度 O(1)
3. 总体的时间复杂度: N * log K
  • 思路2: 双端队列
时间复杂度:O (N*1)
package heap;

import java.util.ArrayDeque;
import java.util.Deque;

public class SlidWindowMax_239 {
    public int[] maxSlidingWindow(int[] nums, int k) {
       /*
         *
         * 判断最大元素是否超出滑动窗口,若超出则将最大元素移除队列
         * 可以保证队列内的元素始终小于等于 k 个,这个才是整个算法的关键
         * 注意队列里放的是元素的索引,而不是元素的值
         * */
        if (nums == null || k <= 0) {
            return new int[0];
        }
        int n = nums.length;
        int[] r = new int[n - k + 1];
        int ri = 0;

        //store index
        Deque<Integer> q = new ArrayDeque<>(k);

        for (int i = 0; i < nums.length; i++) {
            // remove numbers out of range k

            if (!q.isEmpty() && q.peek() < i - k + 1) {
                q.poll();
            }

            // 新的元素 a[i] 要入队,入队之前要先清除比 a[i] 小的元素
            // 新元素进入window要从右侧元素开始比较,不能从左侧比较。
            while (!q.isEmpty() && nums[q.peekLast()] <= nums[i]) {
                q.pollLast();
            }

            q.offer(i);

            if (i >= k - 1) {
                r[ri++] = nums[q.peek()];
            }
        }
       return r;
    }
}