leetcode 239. 滑动窗口最大值、347.前 K 个高频元素

server/2024/9/24 6:48:13/
leetcode_239_347_K__0">leetcode 239. 滑动窗口最大值、347.前 K 个高频元素
leecode 239. 滑动窗口最大值
leetcodecnproblemsslidingwindowmaximumdescription_4">题目链接 :https://leetcode.cn/problems/sliding-window-maximum/description/
题目

给你一个整数数组 nums,有一个大小为 k 的滑动窗口从数组的最左侧移动到数组的最右侧。你只可以看到在滑动窗口内的 k 个数字。滑动窗口每次只向右移动一位。
返回 滑动窗口中的最大值 。

示例 1:
输入:nums = [1,3,-1,-3,5,3,6,7], k = 3
输出:[3,3,5,5,6,7]
解释:
滑动窗口的位置 最大值


[1 3 -1] -3 5 3 6 7 3
1 [3 -1 -3] 5 3 6 7 3
1 3 [-1 -3 5] 3 6 7 5
1 3 -1 [-3 5 3] 6 7 5
1 3 -1 -3 [5 3 6] 7 6
1 3 -1 -3 5 [3 6 7] 7

示例 2:
输入:nums = [1], k = 1
输出:[1]

提示:
1 <= nums.length <= 105
-104 <= nums[i] <= 104
1 <= k <= nums.length

解题思路

这道题是单调队列的应用,本来试着直接解出来,但是一直有bug,然后看了题解后发现是单调队列的应用。
单调队列:队列元素之间的关系具有单调性(从队首到队尾单调递增/递减),队首和队尾都可以进行入队出队(即插入删除)操作,本质是由双端队列deque实现。
通常适合解决动态小区间中寻找极值问题。
可以模拟单调递减队列(类比单调栈)
依次加入7,8,6,2,5,五次操作后队内元素排列情况:
1:7
2:8
3:8 6
4:8 6 2
5:8 6 5

1:队内为空,7入队

2:第二个元素 8 > 7 ,7出队 ,8入队

3:第三个元素 6 < 8 , 6入队

4:第四个元素 2 < 6, 2入队

5:第五个元素 5 > 2, 2出队, 5 < 6, 5入队。
这道题的具体实现代码和详细注释如:

java">class MyQueue {Deque<Integer> deque = new LinkedList<>();//弹出元素时,比较当前要弹出的数值是否等于队列出口的数值,如果相等则弹出//同时判断队列当前是否为空void poll(int val) {if (!deque.isEmpty() && val == deque.peek()) {deque.poll();}}//添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出//保证队列元素单调递减//比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2void add(int val) {while (!deque.isEmpty() && val > deque.getLast()) {deque.removeLast();}deque.add(val);}//队列队顶元素始终为最大值int peek() {return deque.peek();}
}class Solution {public int[] maxSlidingWindow(int[] nums, int k) {if (nums.length == 1) {return nums;}int len = nums.length - k + 1;//存放结果元素的数组int[] res = new int[len];int num = 0;//自定义队列MyQueue myQueue = new MyQueue();//先将前k的元素放入队列for (int i = 0; i < k; i++) {myQueue.add(nums[i]);}res[num++] = myQueue.peek();for (int i = k; i < nums.length; i++) {//滑动窗口移除最前面的元素,移除是判断该元素是否放入队列myQueue.poll(nums[i - k]);//滑动窗口加入最后面的元素myQueue.add(nums[i]);//记录对应的最大值res[num++] = myQueue.peek();}return res;}
}//runtime:43 ms
//memory:58.2 MB
知识点

栈,队列,单调队列

注意事项

怎么使用单调队列,单调队列怎么维护队列的值

相关题目

76.最小覆盖子串

leecode 347.前 K 个高频元素
leetcodecnproblemstopkfrequentelementsdescription_120">题目链接 :https://leetcode.cn/problems/top-k-frequent-elements/description/
题目

给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。

示例 1:
输入: nums = [1,1,1,2,2,3], k = 2
输出: [1,2]

示例 2:
输入: nums = [1], k = 1
输出: [1]

提示:
1 <= nums.length <= 105
k 的取值范围是 [1, 数组中不相同的元素的个数]
题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的

进阶:你所设计算法的时间复杂度 必须 优于 O(n log n) ,其中 n 是数组大小。

解题思路

这道题是优先队列的应用。这道题用哈希表+优先队列,我也尝试了挺久的,后来直接看题解了。主要是对优先队列的使用不熟悉。这里介绍一下优先队列。
首先要注意的就是别与队列(queue)搞混了,队列是一种先进先出(First in First out,FIFO)的数据类型。每次元素的入队都只能添加到队列尾部,出队时从队列头部开始出。
优先级队列(priority_queue)其实,不满足先进先出的条件,更像是数据类型中的“堆”。优先级队列每次出队的元素是队列中优先级最高的那个元素,而不是队首的元素。这个优先级可以通过元素的大小等进行定义。比如定义元素越大优先级越高,那么每次出队,都是将当前队列中最大的那个元素出队。
那这道题的具体实现和代码注释如下,建议好好看看优先队列相关的部分:

java">class Solution {//:基于大顶堆实现public int[] topKFrequent1(int[] nums, int k) {Map<Integer,Integer> map = new HashMap<>(); //key为数组元素值,val为对应出现次数for (int num : nums) {map.put(num, map.getOrDefault(num,0) + 1);}//在优先队列中存储二元组(num, cnt),cnt表示元素值num在数组中的出现次数//出现次数按从队头到队尾的顺序是从大到小排,出现次数最多的在队头(相当于大顶堆)PriorityQueue<int[]> pq = new PriorityQueue<>((pair1, pair2) -> pair2[1] - pair1[1]);for (Map.Entry<Integer, Integer> entry : map.entrySet()) {//大顶堆需要对所有元素进行排序pq.add(new int[]{entry.getKey(), entry.getValue()});}int[] ans = new int[k];for (int i = 0; i < k; i++) { //依次从队头弹出k个,就是出现频率前k高的元素ans[i] = pq.poll()[0];}return ans;}
知识点

栈,队列,优先队列

注意事项

怎么使用有点队列,如何使用优先队列去排序,

相关题目
  1. 数组中的第K个最大元素

http://www.ppmy.cn/server/43028.html

相关文章

Linux-命令上

at是一次性的任务&#xff0c;crond是循环的定时任务 如果 cron.allow 文件存在&#xff0c;只有在文件中出现其登录名称的用户可以使用 crontab 命令。root 用户的登录名必须出现在 cron.allow 文件中&#xff0c;如果这个文件存在的话。系统管理员可以明确的停止一个用户&am…

【文末附gpt升级方案】亚马逊与Hugging Face合作:定制芯片低成本运行AI模型的创新探索

亚马逊与Hugging Face合作&#xff1a;定制芯片低成本运行AI模型的创新探索 摘要 本文探讨了亚马逊云部门与人工智能初创公司Hugging Face的合作&#xff0c;旨在通过定制计算芯片Inferentia2在亚马逊网络服务&#xff08;AWS&#xff09;上更低成本地运行数千个AI模型。文章首…

【负载均衡在线OJ项目日记】引入网络库和客户端用户路由功能

目录 引入cpp-httplib库 将编译与运行服务打包 代码 客户端用户路由功能 采用MVC结构进行设计 用户路由功能 路由功能代码 引入cpp-httplib库 对于后端编译与运行模块基本已经设计完成&#xff0c;最后用户是通过网络传递代码等信息&#xff1b;我们就要将这个模块引入…

使用VirtualBox+vagrant创建CentOS7虚拟机

1.VirtualBox 1.1.什么是VirtualBox VirtualBox 是一款开源虚拟机软件。VirtualBox 是由德国 Innotek 公司开发&#xff0c;由Sun Microsystems公司出品的软件&#xff0c;使用Qt编写&#xff0c;在 Sun 被 Oracle 收购后正式更名成 Oracle VM VirtualBox。 1.2.下载Virtual…

echarts-树图、关系图、桑基图、日历图

树图 树图主要用来表达关系结构。 树图的端点也收symbol的调节 树图的特有属性&#xff1a; 树图的方向&#xff1a; layout、orient子节点收起展开&#xff1a;initialTreeDepth、expandAndCollapse叶子节点设置&#xff1a; leaves操作设置&#xff1a;roam线条&#xff1a…

最小生成树

目录 1.生成树2.最小生成树3.求出最小生成树3.1.破圆法3.2.kruskal3.2.1题目类型 1.生成树 对于一张无向连通图G&#xff0c;它的一个连通子图,含有图中全部n个顶点&#xff0c;但只有足以构成一棵树的n-1条边&#xff0c;那么就称这个子图为G的生成树 2.最小生成树 边的权值…

缓存IO与直接IO

IO类型 缓存 I/O 缓存 I/O 又被称作标准 I/O&#xff0c;大多数文件系统的默认 I/O 操作都是缓存 I/O。在 Linux 的缓存 I/O 机制中&#xff0c;数据先从磁盘复制到内核空间的缓冲区&#xff0c;然后从内核空间缓冲区复制到应用程序的地址空间&#xff08;用户空间&#xff0…

输入一串字符,输入想要字符串前*的个数n,判断字符串前*的个数是大于n还是小于n,如果大于n则删除多余的*其它保持不变,如果小于n,则字符串也保持不变

#define _CRT_SECURE_NO_WARNINGS #include <stdio.h> void fun(char* a, int n) {int i 0, j 0, m 0,b0,c0;char* p;p a;//第一步&#xff0c;判断字母前面有多少个*while (p[i] *){j;}printf("字母前*的个数%d\n",j);//求总的字符串长度while (a[m] !…