力扣0084——柱状图中最大的矩形

本文介绍了一种解决柱状图中求最大矩形面积问题的高效算法,通过使用栈和动态规划的思想,降低了时间复杂度至O(n)。算法主要涉及到下标更新、栈的操作以及面积计算。
摘要由CSDN通过智能技术生成

柱状图中最大的矩形

难度:困难

题目描述

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1 。
求在该柱状图中,能够勾勒出来的矩形的最大面积。

示例1

输入:heights = [2,1,5,6,2,3]
输出:10

示例2

输入: heights = [2,4]
输出: 4

题解

对于下标i,要找到最大的下标j和最小的下标k,满足 j < i < k j<i<k j<i<k h e i g h t s [ j ] < h e i g h t s [ i ] heights[j]<heights[i] heights[j]<heights[i] h e i g h t s [ k ] < h e i g h t s [ i ] heights[k]<heights[i] heights[k]<heights[i],则存在一个宽度为 k − j − 1 k-j-1 kj1,高度为 h e i g h t s [ i ] heights[i] heights[i]的矩形,计算该矩形的最大面积

最为直观的做法是遍历每一个柱子,对于每个下标i,向两边遍历寻找对应的下标jk,得到以 h e i g h t s [ i ] heights[i] heights[i]为高的最大矩形宽度并计算矩形的面积,但是此算法的时间复杂度为 O ( n 2 ) O(n^2) O(n2),会超过时间限制

创建两个长度为n的数组 l e f t left left r i g h t right right,对于每个下标i l e f t [ i ] left[i] left[i] r i g h t [ i ] right[i] right[i]分别记录对应的下标jk。初始时, l e f t left left的全部元素为-1 r i g h t right right的全部元素为n

从左到右遍历数组 h e i g h t s heights heights,当遍历到下标i时,进行如下操作:

  • 如果栈不为空且栈顶下标对应的元素大于等于 h e i g h t s [ i ] heights[i] heights[i],则将栈顶下标对应的 r i g h t right right值设为i,重复该操作直到栈为空或者下标的元素小于 h e i g h t s [ i ] heights[i] heights[i]
  • 如果栈不为空,则栈顶下标对应的元素小于 h e i g h t s [ i ] heights[i] heights[i],因此将i对应的 l e f t left left值设为栈顶下标
  • i入栈

遍历结束之后,对于每个下标i,令 i = l e f t [ i ] , k = r i g h t [ i ] i=left[i],k=right[i] i=left[i],k=right[i],则有 h e i g h t s [ j ] < h e i g h t s [ i ] heights[j]<heights[i] heights[j]<heights[i] h e i g h t s [ k ] < h e i g h t s [ i ] heights[k]<heights[i] heights[k]<heights[i],如果 h e i g h t s [ k ] = h e i g h t s [ i ] heights[k]=heights[i] heights[k]=heights[i],那么高度为 h e i g h t s [ i ] heights[i] heights[i]的最大矩形宽度为 k − j − 1 k-j-1 kj1

所以最大面积为比对之后的最大值

想法代码

class Solution
{
    public static void Main(String[] args)
    {
        Solution solution = new Solution();
        int[] heights = { 2, 1, 5, 6, 2, 3 };
        int ans = solution.LargestRectangleArea(heights);
        Console.WriteLine(ans);
    }

    public int LargestRectangleArea(int[] heights)
    {
        int[] left = new int[heights.Length];
        int[] right = new int[heights.Length];
        Array.Fill(left, -1);
        Array.Fill(right, heights.Length);
        Stack<int> stack = new Stack<int>();
        for (int i = 0; i < heights.Length; i++)
        {
            int height = heights[i];
            while (stack.Count > 0 && heights[stack.Peek()] >= height)
            {
                right[stack.Pop()] = i;
            }

            if (stack.Count > 0)
            {
                left[i] = stack.Peek();
            }
            stack.Push(i);
        }

        int ans = 0;
        for (int i = 0; i < heights.Length; i++)
        {
            ans = Math.Max(ans, (right[i] - left[i] - 1) * heights[i]);
        }
        return ans;
    }
}
s[i]);
        }
        return ans;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值