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

柱状图中最大的矩形

难度:困难

题目描述

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

示例1

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

示例2

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

题解

对于下标i,要找到最大的下标j和最小的下标k,满足 j < i < k jj<i<k h e i g h t s [ j ] < h e i g h t s [ i ] heights[j]heights[j]<heights[i] h e i g h t s [ k ] < h e i g h t s [ i ] heights[k]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[j]<heights[i] h e i g h t s [ k ] < h e i g h t s [ i ] heights[k]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;
    }
}

你可能感兴趣的:(算法进修,leetcode,算法,职场和发展)