【40讲系列3】优先队列

一、实现机制

1. 堆Heap(Binary、Fibonacci)

  对于堆的底层实现,要会白板编程。

2. 二叉搜索树(BST)

二、典型例题

①:返回数据流中的第K大元素(LC703)

class KthLargest {

    private int k;
    private PriorityQueue<Integer> minHeap;
    //使用整数 k 和整数流 nums 初始化对象。
    public KthLargest(int k, int[] nums) {
        this.k = k;
        minHeap = new PriorityQueue<>(k); // 初始化后提高效率
        for (int num : nums){
            add(num);
        }
    }

    //返回当前数据流中第 k 大的元素。
    public int add(int val) {
        if (minHeap.size() < k){
            minHeap.offer(val);
        }else if (val > minHeap.peek()){
            minHeap.poll();
            minHeap.offer(val);
        }
        return minHeap.peek();
    }
}

 

剑指29.最小的K个数

剑指63.数据流中的中位数

②:返回滑动窗口中的最大值(LC239、剑指64.滑动窗口的最大值

方法1:维护大顶堆O(nlog k)

方法2:双端队列O(n)

有3个需要注意的点:

    • 1. 分清头和尾,尾进头出。
    • 2. 记住deque里面存的是索引,而不是值。
    • 3. 返回结果的数组的索引可以省去。
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if (nums == null || nums.length == 0 || k < 1)
            return nums;

        int[] res = new int[nums.length - k + 1];
//        int index = 0; // 结果数组的索引可以省去
        Deque<Integer> deque = new LinkedList<>();
        for (int i = 0; i < nums.length; i++) {
            // 1. 头
            if (!deque.isEmpty() && (i - deque.getFirst()) >= k){
                deque.removeFirst();
            }
            // 2. 尾
            while (!deque.isEmpty() && nums[deque.getLast()] <= nums[i]){
                deque.removeLast();
            }
            // 3. 尾
            deque.addLast(i);
            // 4. 头
            if (i >= k - 1){
                res[i-k+1] = nums[deque.getFirst()];
            }
        }
        return res;
    }
}

 

三、扩展例题

第一组:LeetCode347. 前 K 个高频元素LeetCode23. 合并K个升序链表

 

posted @ 2020-11-20 17:14  不学无墅_NKer  阅读(174)  评论(0编辑  收藏  举报