• Leetcode 84 求直方图中矩形的最大面积


    题目描述

    Leetcode 84 给定 n 个正整数的列表,表示矩形的高度,表示直方图。每一个给出的矩形宽度是 1,找到在直方图里最大的矩形面积。

    img

    如图中给出的直方图,宽度是 1,给出的高度是 [2,1,5,6,2,3].

    可以在直方图中找出最大的隐藏面积,答案是 10.

    img

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

    题目分析

    解法一:

    最后矩形的最大面积,肯定是以某个矩形为最矮高度,向左向右可扩展的最大面积。

    举例子来说,假设以 6 为当前直方图中的最矮高度,分别向左和向右扩展,但发现没有找到比自己还高的。那么以 6 为最矮高度的矩形面积是 6.

    如果以 2 以当前直方图中的最矮高度,向左向右扩展后,发现左面高度为5, 6 的矩形和右面为 3 的矩形,都比自己高。那么以 2 为最矮高度的矩形面积是 2 + 2+ 2 + 2 = 8.

    所以,依次以每个位置的矩形为最矮位置,然后依次拓展就能找到最大的矩形面积了。

    class Solution:
        def largestRectangleArea_old(self, heights: List[int]) -> int:
            """
            O(n^2) -> 超时了,无法提交成功
            :param heights:
            :return:
    
             思路:最后形成最大的矩形面积,肯定是以给定的数组中某个位置连续矩形的最矮位置。
             从 index=0 的位置开始,假定它是这样的位置,然后向左向右开始扫描,找出其连续的矩形
             面积,然后依次比较这些找到的矩形面积。
            """
            max_area = 0
            index = 0
            list_length = len(heights)
            while index < list_length:
                area = heights[index]
                left_index = index - 1
                while left_index > -1:
                    if heights[left_index] >= heights[index]:
                        area += heights[index]
                        left_index -= 1
                    else:
                        break
    
                right_index = index + 1
                while right_index < list_length:
                    if heights[right_index] >= heights[index]:
                        area += heights[index]
                        right_index += 1
                    else:
                        break
                max_area = max_area if max_area > area else area
                index += 1
    
            return max_area
    

    但可以发现,依次遍历每个矩形的位置,时间复杂度为 O(n^2).

    解法二:

    如解法 1 提到的,最大的矩形面积其实就是以某个矩形为最矮位置可扩展的最大面积。这里使用的数据结构是单调递增栈,用于保存局部矩形的峰值。

    单调栈就是在栈里的元素,按照一定的规则进行排序。在本题里,栈里记录的是给定的矩形高度的位置。依次去循环 heights 里的元素,如果比栈顶的元素的大,那么就将元素入栈。如果比栈顶元素的小,就需要出栈,计算以当前栈顶元素形成的矩形面积,直到遇到和要入栈元素一样高的位置再停止。

    需要注意的地方是:

    • 给定的元素可能是一直递增的,所以需要给 heights 末尾添加一个元素 0,用于计算之前的面积。
    • 需要考虑出栈后,站内元素为 0 的情况,这时需要计算,最低矩形高度可以形成的连续矩形面积的情况。例如 [2,1,2] 这种情况。
    class Solution:
        def largestRectangleArea(self, heights: List[int]) -> int:
            # add 0 to query the last local peak area
            # if the last height is still the highest
            heights.append(0)
            # definite a stack to record the heights position
            # to get the local peak area
            heights_position = []
            max_area = 0
            #
            index = 0
            while index < len(heights):
                if len(heights_position) == 0 or heights[heights_position[-1]] <= heights[index]:
                    heights_position.append(index)
                    index += 1
                else:
                    popped_position = heights_position.pop()
                    # get the continuous area of the smallest rectangle
                    # index represents the the number of elements has been processed
                    if len(heights_position) == 0:
                        max_area = max(max_area, index * heights[popped_position])
                    # Get maximum area of rectangle in monotonically increasing
                    else:
                        # index need to reduce 1 because the we add a 0
                        #  to the end of heights array.
                        max_area = max(max_area,
                                       (index - 1 - heights_position[-1]) * heights[popped_position])
            return max_area
    

    对于解法 2 来说,每个元素最多会入栈和出栈一次,所以时间复杂度为 O(2n) 也就是 O(n).

  • 相关阅读:
    flink checkpoint机制的实现
    openjdk源码分析之AtomicLong
    cpp之宏和函数调用约定
    JNA 相关问题
    spark RDD
    最长连续序列
    买卖股票的最佳时机
    二叉树展开为链表
    不同的二叉搜索树
    柱状图中最大的矩形
  • 原文地址:https://www.cnblogs.com/michael9/p/12100953.html
Copyright © 2020-2023  润新知