- 239. 滑动窗口最大值
暴力算法:数组从前到后遍历,下标每次移动都比较一次窗口内的所有元素得出最大值,时间复杂度显然为n*k。 - 很显然,用暴力来做这道题目显然是不符合困难的难度。虽然这题被编排在了栈和队列的章节里面,但是我实在是没有头绪。
- 看了代码随想录提供的思路以及carl视频所说的单调列表的思想,对这题有了初步的了解。由于鄙人数据结构的基础并不是很好,在视频中提到的大顶堆和小顶堆我还特意看了两个视频补了一下课,大顶堆和小顶堆的方法会改变窗口内数组的顺序,因此窗口滑动的时候难以进行窗口内数据的移除。
- 单调队列的思想,就是要始终保持窗口内最大的元素在队头,同时不能改变元素的顺序。在个人的理解中,其实就是将不可能作为滑动窗口中最大值的数提前出队。比如,在本题的示例1中,1是第一个入队的元素,当3将要入队的时候,因为3比1大,因此在3入队后1不可能作为最大值,所以为了让滑动窗口的最大值始终在队头,元素1提前出队。此时,并没有改变原来数组的排列顺序,只是我们让不可能作为最大值输出的数提前出队而已,3依然在5入队的时候弹出。那么代码的逻辑已经很清晰了,元素入队时弹出前面所有小于它的数,每次需要得到滑动窗口最大值时则获取队头的元素,由于我们为了让最大值始终保持在队头,提前弹出了较小的元素,因此不是每次滑动窗口移动时,队列中的队头都要弹出,而是应该队列满了再进行队头元素的弹出。
class MyQueue{ Deque<Integer> deque=new LinkedList<>(); void add(int val){ while(!deque.isEmpty()&&val>deque.getLast()) deque.removeLast(); deque.addLast(val); } void pop(int val){ if(!deque.isEmpty()&&val==peek()) deque.poll(); } int peek(){ return deque.peek(); } } class Solution { public int[] maxSlidingWindow(int[] nums, int k) { MyQueue queue=new MyQueue();//创建自定义的单调列表 //先把窗口填满 for(int i=0;i<k;i++){ queue.add(nums[i]); } int[] result=new int[nums.length-k+1]; //开始进行窗口的移动以及填充最大值数组 int num=0; result[num++]=queue.peek(); for(int i=k;i<nums.length;i++){ //窗口滑动,队头元素弹出 queue.pop(nums[i-k]); //窗口滑动,插入队尾元素 queue.add(nums[i]); //记录新窗口中最大元素 result[num++]=queue.peek(); } return result; } }
- 347.前 K 个高频元素
第一步,要先用hashmap将元素和出现的次数记录下来。
第二步就是要求出hashmap中前k个最大value。
可以将hashmap中的value进行排序后,再用getKey方法进行记录,此时的时间复杂度应该为快速排序的时间复杂度n*logn。但是这样的时间复杂度不满足题目中对时间复杂度的要求 - 更优的解法应该是采用大顶堆或者小顶堆的方法,大顶堆的数据结构完全符合题目的需求,大顶堆中,栈顶一直是堆中元素的最大值,用value构造大顶堆,只需要弹出堆顶元素k次即可,由于大顶堆的数据结构为二叉树,每次弹出后重新形成大顶堆的时间复杂度为logn,因此最终的时间复杂度为klogn。
-
class Solution { public int[] topKFrequent(int[] nums, int k) { Map<Integer,Integer> map=new HashMap<Integer,Integer>(); //遍历数组构造map for(int i=0;i<nums.length;i++){ map.put(nums[i],map.getOrDefault(nums[i],0)+1); } //构造大根堆 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]; //大根堆依次弹出前k个最大元素 for(int i=0;i<ans.length;i++) ans[i]=pq.poll()[0]; return ans; } }
代码随想录算法训练营day13|栈和队列
最新推荐文章于 2024-11-06 08:56:39 发布