第一篇---滑动窗口最大值、前 K 个高频元素

第一篇---滑动窗口最大值、前 K 个高频元素

滑动窗口最大值*

题目链接:链接: 239. 滑动窗口最大值

题目:

---给你一个整数数组 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 ### 思路: 首先要知道输出数组的长度为len-k+1,然后写出添加元素和删除元素的两个方法,在初始化窗口之后,之后的每一次循环将队头元素存入res数组直至循环结束。 **添加元素** :每次添加一个元素时,**保证每一次循环后队头元素是最大的!** (在k\>=2,队列中可以出现相同的最大元素) **删除元素** :在初始化窗口之后,**每一次循环后要保证队列中没有本次窗口之外的元素。**(以示例代码)例如:第一次循环后,保证下标为0的元素(1)不在队列中;第二次循环后,保证下标为1的元素(3)不在队列中 ### 代码: 用时32ms,内存57,3MB ```java class Solution { public int[] maxSlidingWindow(int[] nums, int k) { int n = nums.length; int[] res = new int[n-k+1]; Deque queue = new ArrayDeque<>(); //窗口初始化 for(int i = 0; i < k; i++){ Add(queue,nums[i]); } int index = 0; res[index++] = queue.peek(); //先进行删除操作,后进行添加 for(int i = k; i < n; i++){ Delete(queue,nums[i-k]); Add(queue,nums[i]); res[index++] = queue.peek(); } return res; } //添加元素:比队尾元素大就排出队尾元素,然后继续与队尾比较,这样就能保证每一次循环后队头元素是最大的! public Deque Add(Deque queue, int num){ while(!queue.isEmpty() && num > queue.peekLast()){ queue.pollLast(); } queue.offer(num); return queue; } //删除元素:将本次循环要被删除的元素与队头元素比较,若不相等,则表示在进行添加操作时已经排出了前者,直接进行返回就行;若相等,就要排出队头元素再返回 public Deque Delete(Deque queue,int num){ if(!queue.isEmpty() && num == queue.peek()){ queue.poll(); } return queue; } } ``` 用时41ms,内存58,3MB ```java //自定义数组 class MyQueue { Deque deque = new LinkedList<>(); void poll(int val) { if (!deque.isEmpty() && val == deque.peek()) { deque.poll(); } } //添加元素时,如果要添加的元素大于入口处的元素,就将入口元素弹出 //保证队列元素单调递减 //比如此时队列元素3,1,2将要入队,比1大,所以1弹出,此时队列:3,2 void 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; } } ``` ## 前 K 个高频元素\* 题目链接:链接: [347.前 K 个高频元素](https://leetcode.cn/problems/top-k-frequent-elements/) ### 题目: **---给定一个非空的整数数组,返回其中出现频率前 k 高的元素。** 示例 1: 输入: nums = \[1,1,1,2,2,3\], k = 2 输出: \[1,2

示例 2:

输入: nums = [1], k = 1

输出: [1]

提示:

  • 你可以假设给定的 k 总是合理的,且 1 ≤ k ≤ 数组中不相同的元素的个数。
  • 你的算法的时间复杂度必须优于 O ( n log ⁡ n ) O(n \log n) O(nlogn) , n 是数组的大小。
  • 题目数据保证答案唯一,换句话说,数组中前 k 个高频元素的集合是唯一的。
  • 你可以按任意顺序返回答案。

思路:

1、统计元素出现频率。 【使用map来存储数组中每个元素及其出现的频率】

2、对频率进行排序。 【定义一个小顶堆(使用PriorityQueue来实现):从队头到队尾是由小到大排序】

3、找出前k个高频元素。【当添加进优先级队列中的元素(数组)个数大于k时,排出队头元素,剩下的就是频率前k的元素(数组)】

代码:

用时13ms,内存44.3MB

java 复制代码
class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        //用map获取数组中每个元素及其对应的频率
        Map<Integer,Integer> map = new HashMap<>();
        for(int num : nums)
            map.put(num,map.getOrDefault(num,0) + 1);

        //定义一个堆(lambda 表达式设置优先级队列存储:o1-o2是由小到大,o2-o1是由大到小)
        PriorityQueue<int[]> pq = new PriorityQueue<>((o1,o2)->o1[1] - o2[1]);
        for(Map.Entry<Integer,Integer> entry: map.entrySet()){
            //下面的代码是根据小根堆实现的,我只保留优先队列的最后的k个,只要超出了k我就将最小的弹出,剩余的k个就是答案
            pq.offer(new int[]{entry.getKey(),entry.getValue()});
            if(pq.size() > k){
                pq.poll();
            }
        }
        
        //获取结果
        int[] ans = new int[k];
        for(int i = k - 1; i >= 0; i--){
            ans[i] = pq.poll()[0];
        }
        return ans;
        
    }
}
相关推荐
无敌的牛5 分钟前
vector模拟实现(2)
数据结构
alphaTao7 分钟前
LeetCode 每日一题 2025/3/31-2025/4/6
算法·leetcode
快来卷java12 分钟前
JVM虚拟机篇(五):深入理解Java类加载器与类加载机制
java·jvm·mysql
Andrew_Ryan12 分钟前
android use adb instsll cacerts
算法·架构
Wx120不知道取啥名1 小时前
C语言跳表(Skip List)算法:数据世界的“时光穿梭机”
c语言·数据结构·算法·list·跳表算法
禾小西2 小时前
Java 逐梦力扣之旅_[204. 计数质数]
java·算法·leetcode
LuckyLay2 小时前
LeetCode算法题(Go语言实现)_32
算法·leetcode·golang
ゞ 正在缓冲99%…2 小时前
leetcode295.数据流的中位数
java·数据结构·算法·leetcode·
文弱_书生2 小时前
关于点扩散函数小记
数码相机·算法·数学原理
爪娃侠2 小时前
LeetCode热题100记录-【二叉树】
linux·算法·leetcode