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;
    }
}
相关推荐
Liu6288810 小时前
C++中的工厂模式高级应用
开发语言·c++·算法
AI科技星11 小时前
全尺度角速度统一:基于 v ≡ c 的纯推导与验证
c语言·开发语言·人工智能·opencv·算法·机器学习·数据挖掘
参.商.11 小时前
【Day41】143. 重排链表
leetcode·golang
条tiao条11 小时前
KMP 算法详解:告别暴力匹配,让字符串匹配 “永不回头”
开发语言·算法
干啥啥不行,秃头第一名11 小时前
C++20概念(Concepts)入门指南
开发语言·c++·算法
tobias.b12 小时前
计算机基础知识-数据结构
java·数据结构·考研
zzh9407712 小时前
Gemini 3.1 Pro 硬核推理优化剖析:思维织锦、动态计算与国内实测
算法
2301_8073671912 小时前
C++中的解释器模式变体
开发语言·c++·算法
愣头不青12 小时前
617.合并二叉树
java·算法
MIUMIUKK13 小时前
双指针三大例题
算法