题解 | 柱状图中的最大矩形

题目:

题干解析:

题目给定n个非负整数,假设有n个宽度为1,高度为heights[i]的矩形拼接在一起,题目要求我们返回能够完全被覆盖的矩形的最大值.

首先我们证明这个矩形的高一定是heights中的一个元素,因为如果不是那么要让其完全被覆盖其高度一定就小于height,因此存在另一个矩形,其高度就是height宽度与其相同,则该矩形面积会更大,因此符合题意的矩形高度一定为height数组中的一个元素.

算法思路:

本题其实有三种解决方法,分别为一,二,三次遍历实现,目前我只弄懂了三次遍历实现的方法,因此只讲解此方法.

我们已知符合题意得矩形高度一定为数组中的一个元素,因此我们遍历整个数组针对每个元素进行操作即可获得最大值.同时我们不难理解,要使这个矩形最大,我们只需要找到左起第一个与右起第一个小于该数组元素的元素索引即可,该矩形最大宽度即为两索引相减再减一.

现在问题转化为如何求得从数组中某个元素出发左起与右起第一个小于其的数组索引.已知我们使用单调栈一次循环能够完成一边(左起或右起)的索引发现,我们直接进行两次遍历即可获得两个索引值,此后就如同之前所说,遍历数组获取矩形面积最大值即可.

实现代码:

int largestRectangleArea(vector<int> &heights) {
        stack<int> st;
        const int n = static_cast<int>(heights.size());
        vector<pair<int, int> > range(n, {-1, n});

        // 首次遍历
        st.push(0);
        for (int i = 1; i < n; ++i) {
            if (heights[i] >= heights[st.top()]) st.push(i);
            else {
                while (!st.empty() && heights[i] < heights[st.top()]) {
                    range[st.top()].second = i;
                    st.pop();
                }
                st.push(i);
            }
        }
        while (!st.empty()) {
            range[st.top()].second = n;
            st.pop();
        }

        // 二次遍历
        st.push(n - 1);
        for (int i = n - 2; i != -1; --i) {
            if (heights[i] >= heights[st.top()]) st.push(i);
            else {
                while (!st.empty() && heights[i] < heights[st.top()]) {
                    range[st.top()].first = i;
                    st.pop();
                }
                st.push(i);
            }
        }
        while (!st.empty()) {
            range[st.top()].first = -1;
            st.pop();
        }

        // 三次遍历
        int _max = 0;
        for (int i = 0; i < n; ++i) _max = max(_max, heights[i] * (range[i].second - range[i].first - 1));

        return _max;
    }

复杂度分析:

针对n个正整数:

总计进行三次遍历,每次遍历针对数组元素进行操作花费常数的时间,因此时间复杂度为O(n);

每个元素最坏情况下均得进栈,且需要O(n)的额外空间存储索引值,因此空间复杂度为O(n).

全部评论

相关推荐

12-01 11:06
门头沟学院 C++
数字马力AI工程研发业务初试:1.自我介绍2.项目3.c&nbsp;语言,它里边的这个多线程,它处理的时候,它肯定是存在不稳定的因素嘛,所以说我们要加一些这个策略,再去解决这个不稳定的这个方式。4.比如说两个线程它相互就竞争变成死锁了,那你怎么解决?5.那你&nbsp;Python&nbsp;的语言怎么样?&nbsp;Python&nbsp;你觉得了解程度和&nbsp;C&nbsp;加加相比哪个更好一点?6.Python&nbsp;回文算法的实现,口述。7.你现在常用的都有哪些Linux命令?8.现在想查看一个文件的,相当于我们查看日志吧,不要说文件了,我们就要查看一个日志,而且是实时的,这个命令怎么,是哪个命令?9.实时查看关键字error的命令?10.MySQL数据库的游标。11.MySQL&nbsp;的事务隔离呢?你知道有哪几种?12.更推荐用哪一种事务隔离,为什么?13.就我想现在有一张学生表,我要查询英语成绩是前十名的同学,这个&nbsp;SQL&nbsp;怎么写?14.左右连接的区别15.TCP&nbsp;的三次握手16.TCP四次挥手17.TCP&nbsp;和&nbsp;UDP&nbsp;它们的区别数字马力AI工程研发业务复试:1.自我介绍2.你可以讲一下你在中间你觉得自己成长比较多的那个项目吗?3.项目负责人的话,你这一块的话,你主要的工作包含哪些呢?4.我看你这个项目应该是你刚刚入学读研一的时候,你就在做负责了,是吧?然后那你怎么清楚了解你组内同学,哪些擅长什么呢?你这个是通过什么方式来了解的?5.是对内存的要求会占用会比较那个嘛。那你们这个算法对内存这块就性能方面有,你们性能方面是怎么来做的呢?6.你们有一些内存的话,你们是固定在做分配吧?那有,对于控制内存或者内存释放这一块,你们是什么来做的呢?7.深度学习这方面你有多少了解?8.你对&nbsp;AI&nbsp;这块有多少了解呢?9.挑战杯比赛介绍一下。10.你们做这个挑战杯主要关注哪些方面呢?11.就是如果准确率低的话,关注大模型微调的哪几个点呢?12.比方说一些结构,或者是一些工作流这一块有了解吗?13.Python&nbsp;的那个装饰器有了解吗?14.Python&nbsp;的装饰器的一些特性是什么15.在&nbsp;Python&nbsp;中的话,一般怎么来实现那个多线程呢?16.Python&nbsp;中序列化(对象→字节/字符串)与反序列化(字节&nbsp;/&nbsp;字符串→对象)一般会怎么来做呢?17.你在做项目中,你提出来一个问题。但是你其他的同学或者是你的那个老板并不认同。如果遇到这种问题的话,你一般会怎么处理呢?18.你在学习中,或者是平时遇到一些难题,或者是比较难攻克的一些技术方面的问题,你一般通过什么方式去解决掉呢?反问&nbsp;&nbsp;&nbsp;&nbsp;面试官说可以多了解AI差异化方面的内容数字马力AI工程研发业务复试(三面,面试官没开摄像头):1.自我介绍2.询问第是第几轮面试3.说看我背景是做算法的,然后问了研究方向4.项目介绍,项目的目标是什么5.纯项目...+简单AI6.&nbsp;面试官最后说他是算法方向的,看我简历写的是算法的,然后想考察我的算法能力,应该是没达到他的期望,给挂了。三面都是45分钟左右&nbsp;&nbsp;太难了...
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客网在线编程
牛客网题解
牛客企业服务