算法-单调栈

一、理论基础

  1. 通常是一维数组,要寻找任一个元素的右边或者左边第一个比自己大或者小的元素的位置,此时我们就要想到可以用单调栈了。时间复杂度为O(n)。
  2. 单调栈的本质是空间换时间,就是用一个栈来记录我们遍历过的元素
  3. 单调栈加入的元素是数组的下标

二、每日温度

  1. 题目
    1. 给定一个整数数组 temperatures ,表示每天的温度,返回一个数组 answer ,其中 answer[i] 是指对于第 i 天,下一个更高温度出现在几天后。如果气温在这之后都不会升高,请在该位置用 0 来代替。
  2. 思路
    1. 当前遍历元素大于栈顶元素,表示栈顶元素右边第一个大元素是当前元素,弹出栈顶并记录。
  3. 代码
    class Solution {
        public int[] dailyTemperatures(int[] temperatures) {
            int[] res = new int[temperatures.length];
            Deque<Integer> deque = new LinkedList<>();
            for (int i = 0; i < temperatures.length; i++) {
                while (!deque.isEmpty() && temperatures[i] > temperatures[deque.peek()]) {
                    int index = deque.pop();
                    res[index] = i - index;
                }
                deque.push(i);
            }
            return res;
        }
    }

三、下一个更大元素

  1. 题目
  2. 思路
    1.         对nums2进行处理成单调栈{},并用map记录<值,下一个更大元素的值>
  3. 代码
    class Solution {
        public int[] nextGreaterElement(int[] nums1, int[] nums2) {
            Deque<Integer> deque = new LinkedList<>();
            Map<Integer, Integer> map = new HashMap<>();
            for (int i = 0; i < nums2.length; i++) {
                while (!deque.isEmpty() && deque.peek() < nums2[i]) {
                    map.put(deque.pop(), nums2[i]);
                }
                deque.push(nums2[i]);
            }
            for (int i = 0; i < nums1.length; i++) {
                nums1[i] = map.getOrDefault(nums1[i], -1);
            }
            return nums1;
        }
    }

四、下一个更大元素II

  1. 题目
  2. 思路
    1. 执行两次
  3. 代码
    class Solution {
        public int[] nextGreaterElements(int[] nums) {
            int[] res = new int[nums.length];
            Arrays.fill(res, -1);
            Deque<Integer> deque = new LinkedList<>();
            for (int i = 0; i < 2 * nums.length; i++) {
                while (!deque.isEmpty() && nums[deque.peek()] < nums[i % nums.length]) {
                    res[deque.pop()] = nums[i % nums.length];
                }
                deque.push(i % nums.length);
            }
            return res;
        }
    }

五、接雨水

  1. 题目
    1. 给定 n 个非负整数表示每个宽度为 1 的柱子的高度图,计算按此排列的柱子,下雨之后能接多少雨水。
  2. 思路
    1. 维护大到小单调栈
  3. 代码
    class Solution {
        public int trap(int[] height) {
            Deque<Integer> deque = new LinkedList<>();
            int res = 0;
            for (int i = 0; i < height.length; i++) {
                while (!deque.isEmpty() && height[deque.peek()] < height[i]) {
                    int mid = height[deque.pop()];
                    if (!deque.isEmpty()) {
                        res += (Math.min(height[i], height[deque.peek()]) - mid) * (i - deque.peek() - 1);
                    }
                }
                deque.push(i);
            }
            return res;
        }
    }

六、柱状图中最大的矩形

  1. 题目
    1. 给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。求在该柱状图中,能够勾勒出来的矩形的最大面积。

  2. 思路
    1. 维护小到大单调栈
  3. 代码
    class Solution {
        public int largestRectangleArea(int[] heights) {
            Deque<Integer> deque = new LinkedList<>();
            int[] temp = new int[heights.length + 2];
            temp[temp.length - 1] = 0;
            for (int i = 0; i < heights.length; i++) {
                temp[i + 1] = heights[i];
            }
            int res = 0;
            for (int i = 0; i < temp.length; i++) {
                while (!deque.isEmpty() && temp[deque.peek()] > temp[i]) {
                    int mid = deque.pop();
                    res = Math.max(res, temp[mid] * (i - deque.peek() - 1));
                }
                deque.push(i);
            }
            return res;
        }
    }

七、总结

未完待续

  • 6
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值