当前位置: 首页 > article >正文

代码随想录Day64(一刷完结)

今天学习单调栈解决最后一道题

84.柱状图中的最大矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。

求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例 1:

 

输入:heights = [2,1,5,6,2,3]
输出:10
解释:最大的矩形为图中红色区域,面积为 10

思路:

1.本题初见感觉是类似于Day63的接雨水,但单调栈的思路需要稍微转换一下。

2.相比起前面所有题单调栈是从栈顶到栈尾递增,本题是需要栈顶到栈尾递减才行。至于为什么这么做,相当于我们确定一个矩形的高度作为基准,然后来看他的宽度能延伸到何处(相当于找到左边和右边第一个比自己低的高度,此时就无法继续延伸),进而确定算面积的宽度。

3.但本题还需要考虑一种情况,我们如果完全按照接雨水那道题的步骤去做,会发现当原数组是单调递增或是单调递减时就会出现问题:(1)如果原数组是单调递增,因为我们单调栈是栈顶到栈尾递减,因此此时会一直入栈元素直到遍历完整个数组但却没有进行一次面积计算(因为只有当前元素小于栈顶元素时我们实际上才算找到了一次计算的机会);(2)如果原数组是单调递减,主要涉及到遍历的最初。我们会先将第一个元素压入栈然后从第二个元素开始遍历,但第二个元素比第一个元素小,我们显然需要进行一次计算:以第一个元素为基准,第二个元素是其右边第一个更低的高度,但此时无法找到其左边第一个比自己低的高度

因此为了解决原数组单调的问题,我们在数组首尾各加入一个0,首部加入0解决单调递减时无法找到第一个元素左边第一个比自己低的高度;尾部加入0解决单调递增时不会进行任何一次计算。

class Solution {
public:
    int largestRectangleArea(vector<int>& heights) {
        int result = 0;
        stack<int> st;
        //在原数组首尾插入一个0防止数组纯单调导致发生问题
        heights.insert(heights.begin(), 0);
        heights.push_back(0);
        st.push(0);

        for(int i = 1; i < heights.size(); i++){
            if(heights[i] > heights[st.top()]){
                st.push(i);
            }
            else if(heights[i] == heights[st.top()]){
                st.pop();
                st.push(i);
            }
            else{
                while(!st.empty() && heights[i] < heights[st.top()]){
                    int mid = st.top();
                    st.pop();
                    if(!st.empty()){
                        int left = st.top();
                        int right = i;
                        int w = right - left - 1;
                        int h = heights[mid];
                        result = max(result, w * h);
                    }
                }
                st.push(i);
            }
        }

        return result;
    }
};

启发:

1.对于单调栈这一自己完全不熟系的领域,尽管有了前面一些题的基础,套代码的模板是能套了,但要自己捋清楚思路还是有些困难,在接下来一段时间仍需要继续理解。

2.本题用到了两种变化时定一种的思路,这一思路在之前贪心算法中避免同时考虑两种情况导致顾此失彼时有类似的情况,也相当于是进行了一次复习。

最后的最后,感谢代码随想录总结出来的这一套算法试题,经历了两个月的时间终于全部过完了第一遍,尽管还有不少思想方法自己掌握的不算牢固,但相比起之前几乎零基础的自己也已经提升了不少,也巩固了自己许多基础知识,在以后还会进一步对自己薄弱的环节进行重刷和进一步的集中做题来巩固。完结撒花!


http://www.kler.cn/a/15393.html

相关文章:

  • sapiens推理的安装与使用
  • java设计模式之 - 适配器模式
  • Http常⻅见请求/响应头content-type内容类型讲解(笔记)
  • PG-DERN 解读:少样本学习、 双视角编码器、 关系图学习网络
  • MySQL技巧之跨服务器数据查询:基础篇-A数据库与B数据库查询合并--封装到存储过程中
  • HarmonyOS 如何获取设备信息(系统、版本、网络连接状态)
  • linux0.12
  • Java BIO(Blocking IO:同步并阻塞式IO)
  • idea使用 ( 五 ) idea常用快捷键
  • 知识图谱实战应用6-基于知识推理进行知识补全的功能
  • 「 Redis 」RDB和AOF持久化全面解析
  • 使用Sybase sp_recompile重新编译存储过程和触发器
  • 如何使用osquery在Windows上实时监控文件?
  • Java新提案,最终还是靠近C#了
  • 高度可定制可用于商用目的全流程供应链系统(全部源码)
  • Python 二进制 八进制 十进制 十六进制之间的转换
  • JSP数据库连接池的研究与实现(源代码+论文)
  • 嵌入式安卓开发:使用Camera2获取相机
  • 网络安全真的没法入行吗?
  • RedHat8配置本地YUM源
  • 知识图谱实战应用7-最完整的常用Cypher查询语句与实际应用
  • Unlimited “使用GPT-4 ”!它来了!
  • html学习(布局方式(layout)、浮动(float)、定位(position)、弹性盒(flex))
  • C++设计模式11:享元模式
  • Sharding-JDBC之垂直分库水平分表
  • 结构型模式-享元模式