我们前面费了那么大篇幅介绍堆和优先级队列,就是为了分析本文的7道题。而这7道题,

特别!特别!特别!

重要!重要!重要!

不过呢,正如我们前面说的,这些题目其实知道怎么处理就行,不必一定要写出来。

1.Leetcode23 合并K个排序链表

这个题我们前面曾经花了很大的篇幅来介绍,其中提到一句说可以使用优先级队列来做。原理是不管几个链表,最终都是按照顺序来的。如果使用优先级队列,每次都将剩余节点的最小值加到输出链表尾部,最后堆空的时候,合并也就完成了。

public ListNode mergeKLists(ListNode[] lists) {if (lists == null || lists.length == 0) return null;PriorityQueue<ListNode> q = new PriorityQueue<>(Comparator.comparing(node -> node.val));for (int i = 0; i < lists.length; i++) {if (lists[i] != null) {q.add(lists[i]);}}ListNode dummy = new ListNode(0);ListNode tail = dummy;while (!q.isEmpty()) {tail.next = q.poll();tail = tail.next;if (tail.next != null) {q.add(tail.next);}}return dummy.next;
}

2.LeetCode239 滑动窗口最大值

类似题:剑指offer59

这个题其实就是每次框移动的时候,都输出框的最大值。框的大小就是堆的大小,滑动窗口移动的时候,堆就跟着调整元素,。

public int[] maxSlidingWindow(int[] nums, int k) {if (nums == null || k <= 0) return new int[0];int[] res = new int[nums.length - k + 1];ArrayDeque<Integer> deque = new ArrayDeque<Integer&gt>();int index = 0;for (int i = 0; i < nums.length; i++) {while (!deque.isEmpty()&& deque.peek()< i - k + 1) // Ensure deque's size doesn't exceed kdeque.poll();// Remove numbers smaller than a[i] from right(a[i-1]) to left, to make the first number in the deque the largest one in the window       while (!deque.isEmpty() && nums[deque.peekLast()] < nums[i])deque.pollLast();deque.offer(i);// Offer the current index to the deque's tailif (i >= k - 1)// Starts recording when i is big enough to make the window has k elements res[index++] = nums[deque.peek()];}return res;
}

3.leetcode 264 丑数II

也是剑指offer49题

使用最小堆,要得到从小到大的第 nn 个丑数,可以使用最小堆实现。

初始时堆为空。首先将最小的丑数 11 加入堆。

每次取出堆顶元素 xx,则 xx 是堆中最小的丑数,由于 2x, 3x, 5x2x,3x,5x 也是丑数,因此将 2x, 3x, 5x2x,3x,5x 加入堆。

上述做法会导致堆中出现重复元素的情况。为了避免重复元素,可以使用哈希集合去重,避免相同元素多次加入堆。

在排除重复元素的情况下,第 nn 次从最小堆中取出的元素即为第 nn 个丑数。

class Solution {public int nthUglyNumber(int n) {int[] factors = {2, 3, 5};Set<Long> seen = new HashSet<Long>();PriorityQueue<Long> heap = new PriorityQueue<Long>();seen.add(1L);heap.offer(1L);int ugly = 0;for (int i = 0; i < n; i++) {long curr = heap.poll();ugly = (int) curr;for (int factor : factors) {long next = curr * factor;if (seen.add(next)) {heap.offer(next);}}}return ugly;}
}

4.LeetCode347 前K个高频元素

使用堆的思路与算法

首先遍历整个数组,并使用哈希表记录每个数字出现的次数,并形成一个「出现次数数组」。找出原数组的前 k 个高频元素,就相当于找出「出现次数数组」的前 k 大的值。

最简单的做法是给「出现次数数组」排序。但由于可能有O(N) 个不同的出现次数(其中 NN 为原数组长度),故总的算法复杂度会达到 O(NlogN),不满足题目的要求。

在这里,我们可以利用堆的思想:建立一个小顶堆,然后遍历「出现次数数组」:

如果堆的元素个数小于 k,就可以直接插入堆中。
如果堆的元素个数等于 k,则检查堆顶与当前出现次数的大小。如果堆顶更大,说明至少有 k 个数字的出现次数比当前值大,故舍弃当前值;否则,就弹出堆顶,并将当前值插入堆中。
遍历完成后,堆中的元素就代表了「出现次数数组」中前 k 大的值。

class Solution {public int[] topKFrequent(int[] nums, int k) {Map<Integer, Integer> occurrences = new HashMap<Integer, Integer>();for (int num : nums) {occurrences.put(num, occurrences.getOrDefault(num, 0) + 1);}// int[] 的第一个元素代表数组的值,第二个元素代表了该值出现的次数PriorityQueue<int[]> queue = new PriorityQueue<int[]>(new Comparator<int[]>() {public int compare(int[] m, int[] n) {return m[1] - n[1];}});for (Map.Entry<Integer, Integer> entry : occurrences.entrySet()) {int num = entry.getKey(), count = entry.getValue();if (queue.size() == k) {if (queue.peek()[1] < count) {queue.poll();queue.offer(new int[]{num, count});}} else {queue.offer(new int[]{num, count});}}int[] ret = new int[k];for (int i = 0; i < k; ++i) {ret[i] = queue.poll()[0];}return ret;}
}

5.LeetCode692 前K个高频单词

这个有点复杂,如果用小根堆解决问题的方法是:

先用哈希表统计单词的出现频率,然后因为题目要求前 K 大。所以构建一个 大小为 K 的小根堆按照上述规则自定义排序的比较器。然后依次将单词加入堆中,当堆中的单词个数超过 K 个后,我们需要弹出顶部最小的元素使得堆中始终保留 K 个元素,遍历完成后剩余的 K 个元素就是前 KK 大的。最后我们依次弹出堆中的 K 个元素加入到所求的结果集合中。

代码不写了

堆和优先级队列3:不泡妹子都要会的LeetCode7道题之一相关推荐

  1. 堆和优先级队列4:不泡妹子都要会的LeetCode7道题之二

    本文介绍的两个题比前面的更重要.这两个题的出现频率非常高,虽然每个题都还有多种方式,但是最正统的就是用堆来做.更有意思的是这两个题一般只说方案,不用手写.如果想清楚了就能应付一道面试题,何乐而不为呢? ...

  2. 使用最小堆使用优先级队列(c语言版本)

    下面的例子来自Weiss的<数据结构与算法分析:c语言描述>,自己亲自敲了一遍,跑了个demo,并将结果记录下来. binheap.h的头文件声明 //description: 使最小堆实 ...

  3. 优先级队列 c语言,使用最小堆使用优先级队列(c语言版本)

    下面的例子来自Weiss的<数据结构与算法分析:c语言描述>,自己亲自敲了一遍,跑了个demo,并将结果记录下来. binheap.h的头文件声明 //description: 使最小堆实 ...

  4. 数据结构之堆(Heap),堆的相关操作,用堆模拟优先级队列

    目录 堆的概念 堆的存储方式 堆的相关操作 堆的向下调整. 堆的创建 堆的插入和向上调整 堆的删除 用堆模拟优先级队列 堆的概念 堆是逻辑结构为二叉树存储结构为数组数组的一种数据结构,为什么这么说呢? ...

  5. 《恋上数据结构第1季》二叉堆实现优先级队列

    优先级队列(Priority Queue) 优先级队列简介 优先队列的底层实现 二叉堆实现优先级队列源码 测试代码 数据结构与算法笔记目录:<恋上数据结构> 笔记目录 想加深 Java 基 ...

  6. (补)算法训练Day13 | LeetCode150. 逆波兰表达式求值(栈应用);LeetCode239. 滑动窗口最大值(单调队列);LeetCode347. 前K个高频元素(小顶堆,优先级队列)

    目录 LeetCode150. 逆波兰表达式求值 1. 思路 2. 代码实现 3. 复杂度分析 4. 思考 LeetCode239. 滑动窗口最大值 1. 思路 2. 代码实现 3. 复杂度分析 4. ...

  7. 《算法导论》第六章之堆和优先级队列相关算法C语言实现

    #include <stdio.h> int heap_size = 10; void max_heapify(int *A, int i){ //维持最大堆性质int l = 2 * i ...

  8. 堆(优先级队列)及TOPK问题详解

    文章目录 1.二叉树的顺序存储 1.1存储方式 1.2下标关系 2.堆的应用:优先级队列(默认小根堆) 2.1概念 2.2Java中优先级队列的简单介绍 3.Topk问题 3.1求N个数中前k个最大/ ...

  9. 二叉堆详解实现优先级队列

    二叉堆详解实现优先级队列 文章目录 二叉堆详解实现优先级队列 一.二叉堆概览 二.优先级队列概览 三.实现 swim 和 sink 四.实现 delMax 和 insert 五.最后总结 二叉堆(Bi ...

最新文章

  1. 减少企业Web威胁的三条预防性措施
  2. 北京超级云计算GPU服务器的使用教程
  3. 网页版python叫什么-python脚本和网页有何区别
  4. 【推荐系统】基于模型的协同过滤算法
  5. ansible(自动化运维下)——yaml语言,Role-角色扮演
  6. fread 和 read的区别
  7. 苹果网页归档转html,常用JS转换HTML转义符
  8. [转载] python更新numpy_Python numpy从1.6更新到1.8
  9. 公式冒号是什么意思_冒号是什么意思
  10. matlab绘制x坐标是底数为2的幂函数的折线图
  11. Apple 基于蓝牙的iBeacon技术
  12. 3599元起 铭凡推出NPB7迷你主机:i7-13700H、双雷电4
  13. 认证的公众号可以快速免费注册认证小程序
  14. css 剪辑图片_css实现图片剪裁
  15. 淘宝服务器哪个运营商速度快,三大运营商,谁的宽带网速最快?
  16. 西门子1200PLC大型项目包膜机程序,气缸,通讯,机械手,模拟量等,各种FB块
  17. 南京邮电大学操作系统实验五:Windows平台多进程共享内存通信
  18. Qt利用深度优先搜索实现迷宫寻宝
  19. 19c打补丁简易步骤
  20. Android实现LED数字显示

热门文章

  1. arm64安装docker-compose
  2. Visual Studio创建webapi示例
  3. 故宫景点功课16:内廷西路(上)
  4. 【面经】宁波银行科技部测试岗一面面经
  5. 以太网帧长度大小限制
  6. 谷粒商城Nginx代理网关
  7. 纯QML实现视频播放器
  8. JavaWeb,HTTP和Tomcat
  9. 【Android TV 开发】-->Leanback 中 VerticalGridSupportFragment 的使用
  10. php中json_decode返回数组或对象