单调栈&单调队列总结

单调栈介绍

单调栈的意思是维护一个单调递增或者单调递减的栈, 最通用的解法是找到右边第一个比它大的元素或者找到右边第一个比它小的元素

单调队列介绍

单调队列也是一个维护递增或者递减顺序的队列,一般情况下比单调栈要复杂…适合处理比较复杂的操作,比如滑动窗问题…

通用思路

无论是单调栈还是单调队列,一般都是要O(n)时间复杂度处理"数组", 在while循环中进行单调栈或者单调队列的处理操作。

数据结构具体实现

由于在Java中的Stack性能很差,而且不够灵活,所以不推荐使用.
一般有两种替代方案:
ArrayDeque -----底层为数组
push()----压栈
pop() —出栈
peek() —取栈顶
pollLast() —取栈尾(这里其实有点像队列了…)

LinkedList ----底层为链表

上述两种实现都可以用来实现单调栈或者单调队列…

单调栈例题

  1. 移掉K位数字
class Solution {
    public String removeKdigits(String num, int k) {
        //单调栈
        if (num == null || num.length() == 0) {
            return "";
        }
        LinkedList<Character> stack = new LinkedList<>();
        for (char c : num.toCharArray()) {
            while (k > 0 && !stack.isEmpty() && c < stack.peek()) {
                stack.pop();
                k--;
            }
            //加入栈中, 去掉前导0
            if (c != '0' || !stack.isEmpty()) {
                stack.push(c);
            }
        }
        while (k > 0 && !stack.isEmpty()) {
            stack.pop();
            k--;
        }
        StringBuilder res = new StringBuilder();
        while (!stack.isEmpty()) {
            res.append(stack.pollLast());
        }
        return res.length() == 0 ? "0" : res.toString();
    }
}

84 柱状图中最大的矩形

class Solution {
    public int largestRectangleArea(int[] heights) {
        //维护广义递增(>=)单调栈
        if (heights == null || heights.length == 0) {
            return 0;
        }
        Deque<Integer> stack = new ArrayDeque<>();
        //索引, 非常重要
        int i = 0;
        int area = 0;
        int res = 0;
        while (i < heights.length) {
            if (stack.isEmpty() || heights[i] >= heights[stack.peekFirst()]) {
                stack.offerFirst(i++);
            } else {
                //开始求出某个柱子的最大矩形
                int top = heights[stack.pollFirst()];
                if (stack.isEmpty()) {
                    area = top * i;
                } else {
                    area = top * (i - stack.peekFirst() - 1);
                }
            }
            res = Math.max(res, area);
        }

        //继续处理留在栈里的元素
        while (!stack.isEmpty()) {
            int top = heights[stack.pollFirst()];
            if (stack.isEmpty()) {
                area = top * i;
            } else {
                area = top * (i - stack.peekFirst() - 1);
            }
            res = Math.max(res, area);
        }

        return res;

    }
}

单调队列例题

剑指 Offer 59 - I. 滑动窗口的最大值

class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
        //单调队列, 单调递减队列
        if (nums == null || nums.length == 0) {
            return new int[0];
        }
        Deque<Integer> que = new ArrayDeque<>();
        int[] res = new int[nums.length - (k - 1)];
        int index = 0;
        for (int i = 0; i < nums.length; i++) {
            while (!que.isEmpty() && que.peekFirst() < i - (k - 1)) {
                que.pollFirst();
            }
            while (!que.isEmpty() && nums[que.peekLast()] < nums[i]) {
                que.pollLast();
            }
            que.offerLast(i);
            if (i >= k - 1) {
                res[index++] = nums[que.peekFirst()];
            }
        }
        return res;

    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值