代码随想录算法训练营第五十九天 _ 单调栈_42. 接雨水、84.柱状图中最大的矩形。

学习目标:

单调栈是一种特殊的栈数据结构,在栈的基础上增加了一些特定的性质。它主要用于解决一类与元素大小和顺序有关的问题。

  • 特点:
    单调递增栈:栈内元素从栈底到栈顶呈递增的顺序。
    单调递减栈:栈内元素从栈底到栈顶呈递减的顺序。
  • 实现步骤和规则:
    遍历数组或列表:单调栈通常是通过遍历数组或列表实现的,根据特定条件入栈或出栈
    维护单调性:根据问题的需求,维护栈内元素的单调性(递增或递减)。
    元素的入栈和出栈:根据当前元素和栈顶元素的比较,决定入栈或出栈的规则。
    入栈规则:当前元素满足单调性条件时,入栈。
    出栈规则:当前元素破坏单调性条件时,栈顶元素出栈,直到满足单调性条件为止,再将当前元素入栈。

60天训练营打卡计划!

学习内容:

42. 接雨水

  • 单调栈作用:记录遍历过且没有被计算的元素下标
  • 单调栈顺序:升序(栈底大)
  • 场景:
    ① height[i] > height[st.peek()] — while循环 — 栈顶元素左右两侧的第一个比他大的元素分别是 height[i]栈内的下一个元素
    int base_position = stk.pop();
    if(!stk.empty()){
    w = i - stk.peek() - 1;
    h = Math.min(height[i], height[stk.peek()]) - height[base_position];
    res += w * h;
    }
    ② height[i] <= height[st.peek()] — 构造出了上升栈
    st.push(i)
class Solution {
    public int trap(int[] height) {
        int res = 0;
        // 高度
        int h = 0;
        // 宽度
        int w = 0;

        // 构造递增的单调栈
        Stack<Integer> stk = new Stack<>();
        stk.push(0);

        for(int i = 1; i < height.length; i++){
            if(height[i] <= height[stk.peek()])  stk.push(i);
            else{
                while(!stk.empty() && height[i] > height[stk.peek()]){
                    int base_position = stk.pop();
                    if(!stk.empty()){
                        w = i - stk.peek() - 1;
                        h = Math.min(height[i], height[stk.peek()]) - height[base_position];
                        res += w * h;
                    }
                }
                stk.push(i);
            }
        }
        return res;
    }
}

84.柱状图中最大的矩形

  • 单调栈作用:记录遍历过且没有被计算的元素下标

  • 单调栈顺序:降序(栈底小)

  • 特别要求: 需要在首尾元素前后各增加0

  • 场景:
    ① heights[i] > heights[st.peek()] — while循环 — 栈顶元素左右两侧的第一个比他小的元素分别是 heights[i]栈内的下一个元素
    int base = stk.pop();
    if(!stk.empty()){
    res = Math.max(res, h[base] * (i - stk.peek() - 1));
    }
    ② heights[i] <= heights[st.peek()] — 构造出了下降栈
    st.push(i)

class Solution {
    public int largestRectangleArea(int[] heights) {
        int[] h = new int[heights.length+2];
        // 补0,防止死循环或者空栈错误
        for(int i = 1; i < heights.length+1; i++){
            h[i] = heights[i-1];
        }

        int res = 0;
        // 降序,要找下一个比他小的,栈底小
        Stack<Integer> stk = new Stack<>();
        stk.push(0);

        for(int i = 1; i < h.length; i++){
            if(h[i] >= h[stk.peek()])  stk.push(i);
            else{
                while(!stk.empty() && h[i] < h[stk.peek()]){
                    int base = stk.pop();
                    if(!stk.empty()){
                        // 此处求最大包含面积时候,
                        // 左右两次第一次比他小的位置只作为限制范围,
                        // 不计入真实面积的计算范围
                        res = Math.max(res, h[base] * (i - stk.peek() - 1));
                    }
                }
                stk.push(i);
            }
        }
        return res;
    }
}

学习时间:

  • 上午两个半小时,整理文档半小时。
  • 6
    点赞
  • 8
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
代码随想录算法训练营是一个优质的学习和讨论平台,提供了丰富的算法训练内容和讨论交流机会。在训练营,学员们可以通过观看视频讲解来学习算法知识,并根据讲解内容进行刷题练习。此外,训练营还提供了刷题建议,例如先看视频、了解自己所使用的编程语言、使用日志等方法来提高刷题效果和语言掌握程度。 训练营的讨论内容非常丰富,涵盖了各种算法知识点和解题方法。例如,在第14训练营,讲解了二叉树的理论基础、递归遍历、迭代遍历和统一遍历的内容。此外,在讨论还分享了相关的博客文章和配图,帮助学员更好地理解和掌握二叉树的遍历方法。 训练营还提供了每日的讨论知识点,例如在第15的讨论,介绍了层序遍历的方法和使用队列来模拟一层一层遍历的效果。在第16的讨论,重点讨论了如何进行调试(debug)的方法,认为掌握调试技巧可以帮助学员更好地解决问题和写出正确的算法代码。 总之,代码随想录算法训练营是一个提供优质学习和讨论环境的平台,可以帮助学员系统地学习算法知识,并提供了丰富的讨论内容和刷题建议来提高算法编程能力。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *2* *3* [代码随想录算法训练营每日精华](https://blog.csdn.net/weixin_38556197/article/details/128462133)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v93^chatsearchT3_2"}}] [.reference_item style="max-width: 100%"] [ .reference_list ]

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值