day50 单调栈

单调栈的整体的运用范围: 要保留遍历过元素的状态的时候。

问题1:每日温度

题目:

https://leetcode.cn/problems/daily-temperatures/description/

思路:

最关键的问题:是啥单调栈 递增还是递减

这个如何判断呢 就是看我要比较的 比如说我拿到一个温度 我要去看看 之后比他高的温度对吧 所以啥 应该放递增栈

代码:

java 复制代码
class Solution {
    public int[] dailyTemperatures(int[] temperatures) {
        Deque<Integer> stack = new LinkedList<>();
        int res[] = new int[temperatures.length];
        stack.push(0);
        for(int i = 1; i < temperatures.length; i++){
            // 循环对比
            while(!stack.isEmpty() && temperatures[i] > temperatures[stack.peek()]){
                res[stack.peek()] = i - stack.peek();
                stack.pop();
            }
            // 如果是空的话 那就添加
            stack.push(i);
        }
    return res;
    }
}
问题2:下一个更大的元素I

题目:

https://leetcode.cn/problems/next-greater-element-i/

思路:

在问题1的基础上加了一个映射

代码:

java 复制代码
class Solution {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        Deque<Integer> stack = new LinkedList<>();
        int res[] = new int[nums1.length];
        // 借用hashmap存放nums[1]的映射
        HashMap<Integer,Integer> map = new HashMap<>();
        for(int i = 0; i < nums1.length; i++) res[i] = -1; 
        for(int i = 0; i < nums1.length; i++) map.put(nums1[i],i);
        stack.push(0);
        for(int i = 1; i < nums2.length; i++){
            while(!stack.isEmpty() && nums2[stack.peek()] < nums2[i]){
                if(!map.containsKey(nums2[stack.peek()])){
                    stack.pop();
                }else{
                    res[map.get(nums2[stack.peek()])] = nums2[i];
                    stack.pop();
                }
            }
            stack.push(i);
            }
        return res;
    }
}
问题3:下一个更大的元素II

题目:

https://leetcode.cn/problems/next-greater-element-ii/description/

思路:

在问题2的基础之上 加了个循环的条件 遇见循环考虑用nums[i%len] 一个新的思路

代码:

java 复制代码
class Solution {
    public int[] nextGreaterElements(int[] nums) {
        Deque<Integer> stack = new LinkedList<>();
        int len = nums.length;
        int res[] = new int [len];
        for(int i = 0; i < len; i++) res[i] = -1;
        stack.push(0);
        for(int i = 1; i < len*2; i++){
            while(!stack.isEmpty() && nums[stack.peek()] < nums[i%len]){
                res[stack.peek()] = nums[i%len];
                stack.pop();
            }
            stack.push(i%len);
        }
        return res;
    }
}
问题4:接雨水

题目:

https://leetcode.cn/problems/trapping-rain-water/description/

思路:

在前三道题的基础之上 这里维护的是一个区间

left

right

mid

弄清楚这三个

代码:

java 复制代码
class Solution {
    public int trap(int[] height) {
        if(height.length <=2){
            return 0;
        }
        Stack<Integer> stack = new Stack<>();
        int res = 0;
        stack.push(0);
        for(int i = 1; i < height.length; i++){
            if(height[i] < height[stack.peek()]){
                stack.push(i);
            }else if(height[i] == height[stack.peek()]){
                // 因为相等的相邻墙,左边一个是不可能存放雨水的,所以pop左边的index, push当前的index
                stack.pop();
                stack.push(i);
            }else{
                while(!stack.isEmpty() && height[i] > height[stack.peek()]){
                    // 先记录中间的 把移动放到上面
                    int mid = stack.pop();
                    if(!stack.isEmpty()){
                        int h = Math.min(height[i],height[stack.peek()])-height[mid];
                        int w = i - stack.peek()-1;
                        res += (h*w);
                    }
                }
                stack.push(i);
            }
        }
        return res;
    }
}
问题5:柱状图中的最大的矩形

题目:

https://leetcode.cn/problems/largest-rectangle-in-histogram/description/

思路:

在前三道题的基础之上 这里维护的是一个区间

left

right

mid

弄清楚这三个

其中这里的是单调递减栈

代码:

java 复制代码
class Solution {
    public int largestRectangleArea(int[] heights) {
        if(heights.length == 0){
            return 0;
        }
        // 增加哨兵
        int[] newheight = new int [heights.length + 2];
        newheight[0] = 0;
        newheight[heights.length + 1] = 0;
        for(int i = 0; i < heights.length; i++){
            newheight[i+1] = heights[i];
        }
        // 单调栈的模版题
        Deque<Integer> stack = new LinkedList<>();
        int maxArea = 0;
        stack.push(0);
        for(int i = 0; i < newheight.length; i++){
            if(newheight[i] > newheight[stack.peek()]){
                stack.push(i);
            }else if(newheight[i] == newheight[stack.peek()]){
                stack.pop();
                stack.push(i);
            }else{
                while(!stack.isEmpty() && newheight[i] < newheight[stack.peek()]){
                    int mid = stack.peek();
                    stack.pop();
                    if(!stack.isEmpty()){
                        int left = stack.peek();
                        int right= i;
                        int h = newheight[mid];
                        int w = right - left -1;
                        maxArea = Math.max(maxArea,h*w);
                    }
                }
                stack.push(i);
            }
        }
        return maxArea;
    }
}
相关推荐
澈2073 小时前
深入浅出C++滑动窗口算法:原理、实现与实战应用详解
数据结构·c++·算法
ambition202423 小时前
从暴力搜索到理论最优:一道任务调度问题的完整算法演进历程
c语言·数据结构·c++·算法·贪心算法·深度优先
cmpxr_3 小时前
【C】原码和补码以及环形坐标取模算法
c语言·开发语言·算法
qiqsevenqiqiqiqi3 小时前
前缀和差分
算法·图论
代码旅人ing3 小时前
链表算法刷题指南
数据结构·算法·链表
Yungoal4 小时前
常见 时间复杂度计算
c++·算法
6Hzlia4 小时前
【Hot 100 刷题计划】 LeetCode 48. 旋转图像 | C++ 矩阵变换题解
c++·leetcode·矩阵
不爱吃炸鸡柳5 小时前
单链表专题(完整代码版)
数据结构·算法·链表
CylMK5 小时前
题解:AT_abc382_d [ABC382D] Keep Distance
算法
Dfreedom.5 小时前
计算机视觉全景图
人工智能·算法·计算机视觉·图像算法