[豪の算法奇妙冒险] 代码随想录算法训练营第十一天 | 150-逆波兰表达式求值、239-滑动窗口最大值、347-前k个高频元素

代码随想录算法训练营第十一天 | 150-逆波兰表达式求值、239-滑动窗口最大值、347-前k个高频元素


LeetCode150 逆波兰表达式求值

题目链接:https://leetcode.cn/problems/evaluate-reverse-polish-notation/description/

文章讲解:https://programmercarl.com/0150.逆波兰表达式求值.html

视频讲解:https://www.bilibili.com/video/BV1kd4y1o7on/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 逆波兰表达式是后缀表达式,数字先,运算符号后

​ 所以可以用栈来存数字,遇到运算符再pop两个出来进行相应的运算,再将运算结果放回栈中,这样遍历完表达式,最后栈内留存的结果即为最终的运算结果

image-20251130202627621

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stack = new Stack<>();
        for(String cur : tokens){
            if("+".equals(cur)){
                stack.push(stack.pop() + stack.pop());
            }else if("-".equals(cur)){
                stack.push(-stack.pop() + stack.pop());
            }else if("*".equals(cur)){
                stack.push(stack.pop() * stack.pop());
            }else if("/".equals(cur)){
                int num2 = stack.pop();
                int num1 = stack.pop();
                stack.push(num1 / num2);
            }else{
                stack.push(Integer.parseInt(cur));
            }
        }
        return stack.pop();
    }
}

LeetCode239 滑动窗口最大值

题目链接:https://leetcode.cn/problems/sliding-window-maximum/

文章讲解:https://programmercarl.com/0239.滑动窗口最大值.html

视频讲解:https://www.bilibili.com/video/BV1XS4y1p7qj/?vd_source=b989f2b109eb3b17e8178154a7de7a51

​ 这题有难度,看了Carl哥的讲解才恍然大悟

​ 解这题的思路是使用单调队列,这里采用双端队列Deque实现单调递减队列

​ 为了确保队首元素是最大的,且整个队列单调递减,需要对 poll(int val) 和 offer(int val) 进行重新设计,索性自己再定义一个类

​ poll(int val)应遵守:如果窗口移除的元素value等于单调队列的队首元素,那么队列弹出元素,否则不做任何操作

​ offer(int val)应遵守:如果push的元素value大于队尾元素的数值,那么就将队列队尾的元素弹出,直到push元素的数值小于等于队列入口元素的数值为止,以保证队列的整体单调递减

​ 同时,涉及到栈操作,要确保不能弹出空栈

​ 自定义类设计完成后,回到解题主程序,先将nums数组前k个元素offer进myDeque中,设置cnt=0,记录此时myDeque的队首元素数值到result[cnt++]中

​ 接着就是从nums数组第k个元素(下标从0开始)往后遍历,poll第i-k个元素,offer第i个元素,记录每次的队首元素数值到result[cnt++]中,遍历完成后最终答案即为result数组

image-20251201222032760

class Solution {
    class MyDeque{
        Deque<Integer> que = new LinkedList<>();
        void poll(int val){
            if(!que.isEmpty() && val == que.peekFirst()){
                que.pollFirst();
            }
        }
        void offer(int val){
            while(!que.isEmpty() && val > que.peekLast()){
                que.pollLast();
            }
            que.offerLast(val);
        }
        int peek(){
            return que.peekFirst();
        }
    }

    public int[] maxSlidingWindow(int[] nums, int k) {
        int[] result = new int[nums.length - k + 1];
        int cnt = 0;
        MyDeque myDeque = new MyDeque();

        for(int i = 0;i < k;i++){
            myDeque.offer(nums[i]);
        }
        result[cnt++] = myDeque.peek();

        for(int i = k;i < nums.length;i++){
            myDeque.poll(nums[i-k]);
            myDeque.offer(nums[i]);
            result[cnt++] = myDeque.peek();
        }

        return result;
    }
}

LeetCode347 前k个高频元素

题目链接:https://leetcode.cn/problems/top-k-frequent-elements/description/

文章讲解:https://programmercarl.com/0347.前K个高频元素.html

视频讲解:https://www.bilibili.com/video/BV1Xg41167Lz?vd_source=b989f2b109eb3b17e8178154a7de7a51&spm_id_from=333.788.videopod.sections

​ 先用HashMap记录下nums数组中出现的元素及其次数,然后再采用优先队列按照元素出现次数(value)升序排序,维护一个大小为k的小顶堆

​ 遍历HashMap中键值对,若队列size小于k,则加入队列;若队列size等于k,则将当前队列中次数最少的元素(队首)与当前遍历元素的次数进行比较,将更大的那个留在队列中

​ 遍历完成后,优先队列中存储的k个键值对即为目标,再遍历一遍用result数组接key,即为题目要求答案

​ 这题要注意定义优先队列时,Comparator规则不要写反了,return pair1[1] - pair2[1]为升序排序,实现的是小顶堆,后续只需维护k个元素;return pair2[1] - pair1[1]为降序排序,实现的是大顶堆,需要维护n个元素

image-20251201231545190

image-20251201230701054

class Solution {
    public int[] topKFrequent(int[] nums, int k) {
        HashMap<Integer,Integer> records = new HashMap<>();
        for(int cur : nums){
            int value = records.getOrDefault(cur, 0) + 1;
            records.put(cur, value);
        }

        PriorityQueue<int[]> priorityQueue = new PriorityQueue<>(new Comparator<int[]>(){
            @Override
            public int compare(int[] pair1, int[] pair2) {
                return pair1[1] - pair2[1];
            }
        });

        for(Map.Entry<Integer, Integer> cur : records.entrySet()){
            if(priorityQueue.size() < k){
                priorityQueue.add(new int[]{cur.getKey(), cur.getValue()});
            }else{
                if(cur.getValue() > priorityQueue.peek()[1]){
                    priorityQueue.poll();
                    priorityQueue.add(new int[]{cur.getKey(), cur.getValue()});
                }
            }
        }

        int[] result = new int[k];
        for(int i = 0;i < k;i++){
            result[i] = priorityQueue.poll()[0];
        }

        return result;
    }
}
posted @ 2025-12-01 23:19  SchwarzShu  阅读(0)  评论(0)    收藏  举报