mgaw

导航

< 2025年3月 >
23 24 25 26 27 28 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 1 2 3 4 5

统计

代码随想录算法训练营第十三天| 239 滑动窗口最大值 347 前 K 个高频元素

目录

239 滑动窗口最大值

方法一

方法二

347 前 K 个高频元素


239 滑动窗口最大值

方法一

每次滑动窗口移动都删除队头元素(如果该元素在add中未被删除),如果队尾元素比当前元素小则进行删除操作,确保当前元素为队列中最小值后将当前元素入队,则myQueue中的元素单调递减排序,队头为最大值,队尾为最小值,并将此时的队头元素加入到res数组中,最后返回res数组。

class MyQueue{
    Deque<Integer>deque = new LinkedList<>();
    void poll(int val){
        if(!deque.isEmpty() && val == deque.peek()){//移除队头的元素,需要判断val是否等于deque.peek(),因为nums[i - k]的值可能在add()操作时被删除
            deque.poll();
        }
    }
    void add(int val){
        while(!deque.isEmpty() && val > deque.getLast()){
            deque.removeLast();//去除小于队列中val的元素,保证队列单调递减
        }
        deque.add(val);
    }
    int peek(){//取出队头元素(整个队列的最大值)
        return deque.peek();
    }
}
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        MyQueue myQueue = new MyQueue();
        int len = nums.length - k + 1;//结果中要返回一个长度为len的数组
        int res[] = new int[len];
        int cnt = 0;
        for(int i = 0;i < k;i++){
            myQueue.add(nums[i]);
        }
        res[cnt++] = myQueue.peek();
        for(int i = k;i < nums.length;i++){
            myQueue.poll(nums[i - k]);//去除最前面的元素
            myQueue.add(nums[i]);//加入新元素
            res[cnt++] = myQueue.peek();
        }
        return res;
    }
}

时间复杂度O(n)

空间复杂度O(k)定义了辅助队列myQueue 

方法二

用变量i遍历nums数组,每次滑动窗口移动都先进行判断确保队列的头节点下标大于i - k + 1否则进行删除。

如果队尾元素比nums[i]小则进行删除操作,确保nums[i]为队列中最小值后将i入队,队头则为最大值的下标,deque中存储的下标代表的元素按照单调递减顺序排列。将此时队头元素加入到res数组中。

完成遍历后返回res数组。

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        ArrayDeque<Integer> deque = new ArrayDeque<>();
        int len = nums.length - k + 1;
        int res[] = new int[len];
        int cnt = 0;
        for(int i = 0;i < nums.length;i++){
            while(!deque.isEmpty() && deque.peek() < i - k + 1){//确保队列的头节点在i - k + 1到i的范围内
                deque.poll();
            }
            while(!deque.isEmpty() && nums[deque.peekLast()] < nums[i]){//确保队列单调,队头为整个队列的最大值
                deque.pollLast();
            }
            deque.offer(i);//向队尾添加元素的下标
            if(i >= k - 1){//此时应该向res中添加队列中最大值,即队头的值
                res[cnt++] = nums[deque.peek()];
            }
        }
        return res;
    }
}

时间复杂度O(n)

空间复杂度O(k)定义了辅助队列deque 

347 前 K 个高频元素

构建大顶堆存放nums中元素及其出现频数,最后弹出前k个频数较大的元素。

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        int res[] = new int[k];
        HashMap<Integer,Integer>map = new HashMap<>();
        for(int num : nums){
            map.put(num,map.getOrDefault(num,0) + 1);
        }
        Set<Map.Entry<Integer,Integer>>entries = map.entrySet();
        PriorityQueue<Map.Entry<Integer,Integer>>queue = new PriorityQueue<>((o1,o2) -> o2.getValue() - o1.getValue());//根据map的value值,构建于一个大顶堆(o1 - o2: 小顶堆, o2 - o1 : 大顶堆)
        for(Map.Entry<Integer,Integer> entry : entries){
            queue.offer(entry);
        }
        for(int i = k - 1;i >= 0;i--){
            res[i] = queue.poll().getKey();
        }
        return res;
    }
}

时间复杂度O(nlogk)  每次堆操作花费了O(logk)的时间

空间复杂度O(n)

posted on   A魔法恐龙  阅读(2)  评论(0编辑  收藏  举报  

相关博文:
阅读排行:
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?
点击右上角即可分享
微信分享提示