【力扣刷题】Day12——栈和队列专题

文章目录

    • 5. 逆波兰表达式求值
    • 6. 滑动窗口最大值
    • 7. 前 K 个高频元素


上一篇文章:【力扣刷题】Day11——栈和队列专题_塔塔开!!!的博客-CSDN博客

5. 逆波兰表达式求值

150. 逆波兰表达式求值 - 力扣(LeetCode)

逆波兰表达式:其实就是二叉树的后续遍历(后缀表达式)

思路:栈模拟

  • 遇到数字加入栈
  • 遇到操作字符弹出栈顶两个元素,进行对应操作即可

Code

import java.util.Stack;

class Solution {
    public int evalRPN(String[] tokens) {
        Stack<Integer> stk = new Stack<>();
        for (String s : tokens) {
            if("+".equals(s)) stk.push(stk.pop() + stk.pop());
            else if("-".equals(s)) stk.push(-stk.pop() + stk.pop());// 减号要特殊处理
            else if("*".equals(s)) stk.push(stk.pop() * stk.pop());
            else if("/".equals(s)){
                int x1 = stk.pop();
                int x2 = stk.pop();
                stk.push(x2 / x1);
            }else {
                stk.push(Integer.parseInt(s));
            }
        }
        return stk.pop();
    }
}


6. 滑动窗口最大值

题目链接:239. 滑动窗口最大值 - 力扣(LeetCode)

思路:单调队列求滑动窗口最值,模板题!

class Solution {
    public int[] maxSlidingWindow(int[] a, int k) {
        
        int n = a.length;
        int[] q = new int [1000010];
        int hh = 0, tt = -1;
        List<Integer> list = new ArrayList<>();

        for(int i = 0; i < n; i ++){
            int x = a[i];
            if(hh <= tt && i - k + 1 > q[hh]) hh ++;// 窗口大小 > k
            while(hh <= tt && a[q[tt]] <= x) tt --;// 维护单调队列
            q[++ tt] = i;
            if(i >= k - 1) list.add(a[q[hh]]);// 要够一个窗口的大小
        }
        int len = list.size();
        int[] res = new int[len];
        for(int i = 0; i < len; i ++) res[i] = list.get(i);
        return res;
        
    }
}

7. 前 K 个高频元素

题目链接:347. 前 K 个高频元素 - 力扣(LeetCode)

关于堆:

如果面试题中要求求出一个动态数据集中的最大值或者最小值,那么一般可以考虑使用优先队列(堆)来解决问题
Java 中优先队列(堆) PriorityQueue 的默认情况下是一个最小堆,如果要使用最大堆,那么在调用构造函数时就需要传入 Comparator 的实现类自定义比较排序的规则。 PriorityQueue 实现了接口 Queue,常用函数有:

  • offer(e):将元素 e 放入堆中
  • poll():删除堆顶元素
  • peek():返回位于堆顶的元素,但该元素并不出堆,还在堆中

思路:优先队列

我们可以通过优先队列维护这k个前 K 个高频元素(限制堆的大小为k),维护的依据是元素的出现次数,为此我们可以用一个map对元素和其出现次数进行绑定,维护一个小根堆,重写的排序规则就是根据map的entry对象中的出现次数进行排序(小根堆)。

当我们遍历map集合时,若队列未满,则将entry直接入堆,若满了,则比较当前元素的出现次数是否 >堆顶元素,是则弹出堆顶元素然后当前元素入堆即可!最终堆中的这k个元素即为 前 K 个高频元素。

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

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

        // 优先级队列维护频率前k高元素
        PriorityQueue<Map.Entry<Integer, Integer>> heap = new PriorityQueue<>(new Comparator<Map.Entry<Integer, Integer>>() {
            @Override
            public int compare(Map.Entry<Integer, Integer> o1, Map.Entry<Integer, Integer> o2) {
                return o1.getValue() - o2.getValue();
            }
        });
        // 遍历哈希表,将entry入队
        // 小根堆中维护k个频率(高频率)的数字
        for (Map.Entry<Integer, Integer> entry : mp.entrySet()) {
            if(heap.size() < k){// 队列未满,直接加入
                heap.offer(entry);
            }else {
                // 队列满,则当前元素的出现次数大于堆顶的元素的出现次数,则删除堆顶元素
                Map.Entry<Integer, Integer> top = heap.peek();
                if(entry.getValue() > top.getValue()){
                    heap.poll();
                    heap.offer(entry);
                }

            }
        }
        // 此时 heap中的k个entry就是 频率前k高的元素
        int[] res = new int[heap.size()];
        int cnt = 0;
        for (Map.Entry<Integer, Integer> entry : heap) {
            res[cnt ++] = entry.getKey();
        }
        return res;

    }
}


你可能感兴趣的:(代码随想录力扣刷题,leetcode,算法,职场和发展)