【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(); } }
②:返回滑动窗口中的最大值(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个升序链表