day13 栈与队列 | 239,347

文章介绍了如何使用单调队列解决LeetCode239题,维护一个单调递减的队列以找到滑动窗口的最大值。同时,文章还展示了在LeetCode347题中利用最小堆实现TopK频繁元素的查找,通过统计频率并构建小顶堆来找出出现频率最高的k个元素。
摘要由CSDN通过智能技术生成

LeetCode 239 力扣

* 维护一个单调队列

* 入队列时,保证单调递减(可以将小于待入队的数全部移除)

* 出队列,如果不是队首出(最大元素),无需处理

package algor.trainingcamp;

import java.util.Deque;
import java.util.LinkedList;

/**
 * @author lizhe
 * @version 1.0
 * @description: TODO
 * @date 2023/4/18 08:21
 *
 */
public class LeetCode239_RE {
    public int[] maxSlidingWindow(int[] nums, int k) {
        if(null == nums){
            return nums;
        }

        int size = nums.length - k + 1;
        int[] res = new int[size];
        int idx = 0;

        //先将前k个元素放入队列
        MySimpleQueue queue = new MySimpleQueue();
        for(int i = 0;i < k;i++){
            queue.add(nums[i]);
        }
        //前k个元素产生一个最大值
        res[idx++] = queue.peek();

        //从k到nums.length - 1进行队列的出入
        /**
         * 出: nums[i - k]
         * 入: nums[i]
         */
        for(int i = k;i < nums.length;i++){
            queue.poll(nums[i - k]);
            queue.add(nums[i]);
            res[idx++] = queue.peek();
        }

        return res;
    }
}

/**
 * 维护一个单调队列
 * 1、插入时,维护单调递减即可 eg: 4,2 如果需要插入3 可以将小于3的值全部移除
 * 2. 删除时,如果不是最大的值,无需删除
 * 3. peek 找到队列顶部即可
 */
class MySimpleQueue {
    Deque<Integer> queue = new LinkedList<>();

    /**
     * 插入元素时,将小于待插入元素的数据全部移除
     */
    public void add(int val){
        while(!queue.isEmpty() && val > queue.getLast()){
            queue.removeLast();
        }

        queue.add(val);
    }

    /**
     * 弹出元素
     * 如果发现队列不为空 且 value等于最大值 才需要弹出
     */
    public void poll(int value){
        if(!queue.isEmpty() && value == queue.peek()){
            queue.poll();
        }
    }

    public int peek(){
        return queue.peek();
    }
}

LeetCode 347 力扣

* TOPK 先记录下单词的频次,再使用最小堆处理

package algor.trainingcamp;

import java.util.HashMap;
import java.util.Map;
import java.util.PriorityQueue;
import java.util.Set;

/**
 * @author lizhe
 * @version 1.0
 * @description: 给你一个整数数组 nums 和一个整数 k ,请你返回其中出现频率前 k 高的元素。你可以按 任意顺序 返回答案。
 * @date 2023/4/17 08:04
 *
 * 1. 统计出现频率
 * 2. 构建小顶堆(小顶堆每次弹出都是堆顶的元素),留下了最大的N个数
 * 3. 每次进行小顶堆出堆 直到剩下N个数
 */
public class LeetCode347 {
    public int[] topKFrequent(int[] nums, int k) {
        Map<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) -> o1.getValue() - o2.getValue());

        for (Map.Entry<Integer, Integer> entry : entries) {
            queue.offer(entry);

            if(queue.size() > k){
                queue.poll();
            }
        }

        int[] res = new int[k];
        for(int i = k - 1;i >= 0;i--){
            res[i] = queue.poll().getKey();
        }

        return res;
    }

    public static void main(String[] args) {
        LeetCode347 demo = new LeetCode347();
        demo.topKFrequent(new int[]{1,1,1,2,2,3}, 2);
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值