【leetcode】柱状图中最大的矩形(第二遍)

题目链接

【题解】

考虑每个柱子为最高柱子对答案的贡献,就是看这个柱子往左能domain多少个单位
往右能domain多少个单位。
遇到比它小的为止
遍历所有的柱子为最高柱子的情况.
就能够覆盖到所有的矩形了。

也即枚举一个位置然后如果比它高就一直扩展,往左往右各做一次就好。
这样的时间复杂度是O(N^2)的

我们可以维护一个单调递增的队列。
这个队列里面第i个元素和第i-1个元素
假设他们原来在数组里的位置是
ii和jj
显然min(ii+1,jj)..jj这一段里面的柱子都是比i元素也即在原来中的jj位置的柱子
来得高的。
同时单调队列栈顶的元素所在的位置设为kk
jj..kk这一段的柱子显然也是全都高于jj
所以贡献就能算出来了。
(sta[top]-sta[cur-1])*height[sta[cur]];
对于每一个算贡献的cur,显然没必要再往右扩展了。
因为算这个答案的时候,实际上。就是因为遇到了一个比栈顶的元素矮的柱子。
那每个比它高的柱子,刚好就不能再继续往右扩展了。
因此算法是正确的。

这题的关键就在于,想到枚举每个柱子是最高元素,然后往左往右扩展这一步。
从而联想到用单调队列的性质加速这个找左边界和右边界的过程.

【代码】

class Solution {
public:

    int largestRectangleArea(vector<int>& heights) {
        int sta[100000+10];
        int top = 0;
        int ans = 0;
        sta[0] = -1;
        for (int i = 0;i < (int)heights.size();i++){
            if (top==0 || heights[i]>=heights[sta[top]]){
                sta[++top] = i;
            }else{
                while (top>0 && heights[i]<heights[sta[top]]){
                    ans = max(ans,((i-1)-sta[top-1])*heights[sta[top]]);
                    top--;
                }
                sta[++top] = i;
            }
            //             for (int j = 1;j<=top;j++){
            //     cout<<sta[j]<<" ";
            // }
            // cout<<endl;
        }
        while (top>0){
            ans = max(ans,((int)heights.size()-1-sta[top-1])*heights[sta[top]]);
            top--;
        }
        return ans;
    }
};

原文地址:https://www.cnblogs.com/AWCXV/p/12289778.html

时间: 2024-08-28 22:20:07

【leetcode】柱状图中最大的矩形(第二遍)的相关文章

【LeetCode 85】最大矩形(第二遍)

题目链接 [题解] 首先 我们处理出来一个数组 a[i][j]. 这个数组的含义是,矩阵中(i,j)包括自身往上有多少个连续的1. 然后我们枚举行i. 表示我们现在要考察的矩阵的下边在第i行. 然后我们再处理出来一个一维数组heights[j] 其中heights[j] = a[i][j] 然后,问题就转化为在一个柱状图里面求一个最大的矩形了.用这个方法 做就行了. 枚举行O(N)的复杂度,柱状图求最大的矩阵也是O(N)的复杂度 因此这道题的时间复杂度为O(N^2) [代码] class Sol

开始刷第二遍

从9月12号开始,到现在三个多月了,现在进度是300/304,后面几题难度比较大,尤其是dietpepsi加的一些Dynamic Programming的新题,自己往往做不出来要去看答案.今天起决定暂停做新题了,从头开始刷第二遍,之后的新题目,等到第二遍结束的时候再尝试挑战. 第二遍打算在两个月内刷完,研究Discuss版,争取每道题目能有最优解法和多种解法, 也要进行仔细和正确的复杂度分析,注意coding style以及coding convention.同时还要全面补强数据结构和算法的知识

Winform and WPF 第二遍双击快捷方式或应用程序打开原来的应用程序而不新建一个实例[进程通信 1]

private void Window_Loaded(object sender, RoutedEventArgs e)         {             Process[] pro = Process.GetProcesses();             int n = pro.Where(p => p.ProcessName.Equals("进程名称")).Count();             if (n > 1)             {      

Leetcode84. 柱状图中最大的矩形(单调栈)

84. 柱状图中最大的矩形 前置 单调栈 做法 连续区间组成的矩形,是看最短的那一块,求出每一块左边第一个小于其高度的位置,右边也同理,此块作为最短限制.需要两次单调栈 单调栈维护递增区间,每次不满足弹出栈顶,顺便利用此栈顶和当前位置计算栈顶能覆盖的长度 用来计算.仅需一次单调栈 原文地址:https://www.cnblogs.com/y2823774827y/p/11261446.html

[LeetCode] 84. 柱状图中最大的矩形

题目链接 : https://leetcode-cn.com/problems/largest-rectangle-in-histogram/ 题目描述: 给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]. 图中阴影部分为所能勾勒出的最大矩形面积,其面积为 10 个单位. 示例: 输入: [2,1,5,6,2,3] 输出:

【leetcode 33】搜索旋转排序数组(第二遍)

题目链接 [题解] 如果没有旋转这么一说. 那么问题就是一道普通的二分查找的题目. 加上旋转之后.也没有让这个题变难多少. 问题的关键在于. 在二分查找的时候. 能够想到用nums[0]这个元素来确定当前二分枚举到的元素是在哪一个区间里面的. 即是在左边那个上升区间里面,还是在右边那个上升区间里面. 不过. 知道在哪个区间以后 还有一个问题. 就是我们不能单纯的就在那个区间里面做二分. 因为那个元素可能是在另外一个区间里的. 所以还得拿目标元素和nums[0]做一个对比. 比它小然后nums[m

LeetCode:Rectangle Area - 矩形交叉部分的面积

1.题目名称 Rectangle Area(矩形交叉部分的面积) 2.题目地址 https://leetcode.com/problems/rectangle-area/ 3.题目内容 英文:Find the total area covered by two rectilinear rectangles in a 2D plane. Each rectangle is defined by its bottom left corner and top right corner as shown

LeetCode:Second Highest Salary - 第二高的工资

1.题目名称 Second Highest Salary(第二高的工资) 2.题目地址 https://leetcode.com/problems/second-highest-salary/ 3.题目内容 现在有一张记录了Id(主键)和Salary(工资)的表,求出其中第二高的工资.如果不存在第二高的工资,返回null. +----+--------+ | Id | Salary | +----+--------+ | 1  | 100    | | 2  | 200    | | 3  | 

LeetCode84:柱状图中最大的矩形

给定 n 个非负整数,用来表示柱状图中各个柱子的高度.每个柱子彼此相邻,且宽度为 1 . 求在该柱状图中,能够勾勒出来的矩形的最大面积. 以上是柱状图的示例,其中每个柱子的宽度为 1,给定的高度为 [2,1,5,6,2,3]. 首先定义: 对柱形图中的一个矩形i来说,我们计算以heights[i]为高的矩形的最大面积时,以i为起点,向左找到第一个小于heights[i]的矩形j,向右找到第一个小于heights[i]的矩形k.(j,k)区间,也即[j+1,k-1]所围成的以heights[i]的