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的基础之上 加了个循环的条件 遇见循环考虑用numsi%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;
    }
}
相关推荐
QXWZ_IA19 小时前
1库1图1批是什么?千寻位置公安地图数据体系详解
科技·算法·能源·媒体·交通物流·政务
c2385619 小时前
Bug 猎手入门指南
c++·算法·bug
Reart20 小时前
Leetcode 213.打家劫舍2(内含闲谈,打劫真是技术活,好题,716)
后端·算法
Reart21 小时前
Leetcode 198.打家劫舍(716)
后端·算法
Jerry21 小时前
LeetCode 110. 平衡二叉树
算法
玖玥拾21 小时前
C++ 数据结构 八大基础排序算法专题
数据结构·c++·算法·排序算法
Tim_1021 小时前
【C++】017、new/delete与malloc/free的区别
java·数据结构·算法
从零开始的代码生活_1 天前
C++ list 原理与实践:双向链表、迭代器与简化实现
开发语言·c++·后端·学习·算法·链表·list
ttod_qzstudio1 天前
【软考算法】软件设计师下午第四题之动态规划:0-1 背包与最长公共子序列的“填表艺术“
算法·动态规划·软考