数据结构 - 单调栈、单调队列

单调栈:每日温度

  • 请根据每日 气温 列表 temperatures ,请计算在每一天需要等几天才会有更高的温度。如果气温在这之后都不会升高,请在该位置用 0 来代替
  • 单调栈基本只处理NGE问题(Next GreaterElement)。对序列中每个元素,找到下一个比它大的元素。(“下一个”可以换成“上一个”,“大”也可以换成“小”)
class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        // NGE问题,单调栈,按温度递减的顺序,排列日期
        Deque<Integer> descStack = new LinkedList<>();
        int[] result = new int[temperatures.length];
        for (int i = 0; i < temperatures.length; i++) {
        	// 保证栈是递减的
            while (descStack.size() > 0 && temperatures[descStack.peekLast()] < temperatures[i] ) {
                int topDay = descStack.pollLast();
                result[topDay] = i - topDay;
            }
            descStack.offerLast(i);
        }
        return result;
    }
}

单调队列:滑动窗口的最大值

  • 给定一个数组 nums 和滑动窗口的大小 k,请找出所有滑动窗口里的最大值(典型用法)

  • 详细参考

"""
用一个queue(滑动窗口,先入先出)和一个deque实现
queue负责push和pop,deque用来存放最大值
1. 如果新的value大于deque尾端的值,那么deque一直进行pop_back操作,直到尾端的值大于等于value 或者为空,再将value压入deque的尾部
2. 每次取max_value,返回deque首部的值
3. 当que进行pop操作时,如果que首部的值等于deque首部的值,那么deque同样需要进行pop_front操作
"""
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        // 单调队列
        Deque<Integer> queue = new LinkedList<>();
        List<Integer> result = new LinkedList<>();
        // 窗口不满,处理前k个值
        for (int i = 0; i < k; i++) {
            while (!queue.isEmpty() && queue.peekLast() < nums[i]) {
                queue.pollLast();
            }
            queue.offerLast(nums[i]);
        }
        result.add(queue.peekFirst());
        // 窗口已满,处理后续值
        for (int i = k; i < nums.length; i++) {
            int outVal = nums[i - k];
            int inVal = nums[i];
            // 最大值出窗口,要在队列中同步删除
            if (outVal == queue.peekFirst()) {
                queue.pollFirst();
            }
            // 新值进窗口
            while (!queue.isEmpty() && queue.peekLast() < nums[i]) {
                queue.pollLast();
            }
            queue.offerLast(nums[i]);
            result.add(queue.peekFirst());
        }
        return result.stream().mapToInt(Integer::intValue).toArray();
    }
}

单调队列:队列的最大值

  • 栈的最值比较简单(每次入栈两个元素,一个当前值,一个当前最值)
class MaxQueue {

    // 单调队列,用于统计当前队列的最值
    Deque<Integer> deque = new LinkedList<>();
    // 存放当前队列的所有元素
    List<Integer> list = new LinkedList<>();

    public MaxQueue() {

    }
    
    public int max_value() {
        if (deque.isEmpty()) {
            return -1;
        } else {
        	// 单调队列的首部是最值
            return deque.peekFirst();
        }
    }
    
    public void push_back(int value) {
        list.add(value);
        // 维护单调队列使其保持递减
        while (!deque.isEmpty() && deque.peekLast() < value) {
            deque.pollLast();
        }
        deque.offerLast(value);
    }
    
    public int pop_front() {
        if (deque.isEmpty()) {
            return -1;
        }
        int result = list.get(0);
        list.remove(0);
        // 如果出队列的值是当前最大值,同步移除
        if (deque.peekFirst() == result) {
            deque.pollFirst();
        }
        return result;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值