LeetCode 84. Largest Rectangle in Histogram [python3/C++]

转载请注明出处:https://blog.csdn.net/yyying2016/article/details/80119171


一 题目:

Given n non-negative integers representing the histogram's bar height where the width of each bar is 1, find the area of largest rectangle in the histogram.


Above is a histogram where width of each bar is 1, given height = [2,1,5,6,2,3].

 


The largest rectangle is shown in the shaded area, which has area = 10 unit.

Example:

Input: [2,1,5,6,2,3]
Output: 10





二 分析

    1、如果用暴力解法的话,对每个柱子遍历一遍其左右一段连续且比他高的柱子,复杂度为O(n^2),由于该题的数据太大,会导致TLE。

    2、如果用一个栈来维护的话,可以实现O(n)的解法,想法的中心就是从左到右着解决每一个“山峰”,同时记录下当前最大的矩形面积,具体思路如下:

    建立一个空栈,用来记录一个递增的柱体的下标。

    再建立一个int类型的数ans,用来记录目前所得到的最大值。

    (1) 先对柱子的vector进行遍历一遍:

       ① 如果栈为空,或者当前柱子高度高于/等于栈顶元素指向的柱子的高度,则把当前柱子的下标push进栈(保证栈中的柱子高度是递增的)。

       ② 否则,说明当前柱子高度低于栈顶元素指向的柱子的高度,则将栈顶pop出,并判断新栈顶柱子(不包括)到当前柱子(不包括)的长度×pop出的原栈顶的柱子的高度是否大于ans,是则就刷新ans。(这里为什么是新栈顶柱子而不是原栈顶柱子呢?因为在栈里的元素都是经过筛选递增的,连个元素之间是一个“山峰”,但由于被原栈顶元素限制,因此两个元素之间的“山峰”只能看成高度和右边柱子的高度一样,则从新栈顶+1的柱子到原栈顶柱子的高度都被看成一样是原栈顶柱子的高度)

       最后遍历一遍栈,判断从最后一个柱子到新栈顶柱子(不包括)的长度×原栈顶柱子高度是否大于ans,是则刷新ans。

        

        对于步骤②可能看得不太清楚,这里考虑一下上图的例子:

        当前柱子下标为4,则根据步骤①可以知道,栈中的元素为1、2、3。

        此时发现,当前柱子[4]高度小于栈顶柱子[3]高度,则执行步骤②,将栈顶[3]pop出来,新栈顶变为[2],此时计算矩形面积为6*1=6,则ans更新为6;再判断,发现栈顶柱子[2]高度依然高于当前柱子[4]高度,则将栈顶[2]pop出来,新栈顶变为[1],此时再计算矩形面积为5*2=10,ans更新为10;最后将[4]push进栈,栈中元素变为1、4。以此类推。


三 代码

    python版:

class Solution:
    def largestRectangleArea(self, heights):
        """
        :type heights: List[int]
        :rtype: int
        """
        stack = []
        index = 0
        ans = 0
        size = len(heights)
        while index < size:
            if len(stack) == 0 or heights[index] >= heights[stack[-1]]:
                stack.append(index)
                index = index + 1
            else:
                up = heights[stack[-1]]
                stack.pop()
                if len(stack) == 0:
                    ans = max(ans, up * index)
                else:
                    ans = max(ans, up * (index - stack[-1] - 1))
        while len(stack) != 0:
            up = heights[stack[-1]]
            stack.pop()
            if len(stack) == 0:
                ans = max(ans, up * index)
            else:
                ans = max(ans, up * (index - stack[-1] - 1))
        return ans

    C++版:

#include <iostream>
#include <stack>
#include <vector>
using namespace std;

int largestRectangleArea(vector<int>& heights) {
  stack<int> stk;
  int index = 0, ans = 0, size = heights.size();
  
  while(index < size) {
    if(stk.empty() || heights[index] >= heights[stk.top()]) { //栈为空或者第i个柱体高于栈顶柱体 
      stk.push(index++);
    }
    else { //第i个柱体比栈顶柱体矮 
      int up = heights[stk.top()];
      stk.pop();
      int width = stk.empty() ? index : index - stk.top() - 1;
      ans = max(ans, up * width); //新栈顶指示的下标以后的柱体高度和up相同 
    }
  }
  
  while(!stk.empty()) {
    int up = heights[stk.top()];
    stk.pop();
    int width = stk.empty() ? index : index - stk.top() - 1;
    ans = max(ans, up * width);
  }
  return ans;
}

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值