16.最大矩形面积问题 | 豆包MarsCode AI刷题

105 阅读3分钟

中等题:最大矩形面积问题

问题描述

小S最近在分析一个数组h1​,h2​,...,hn​,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 k 个相邻元素时,如何计算它们所能形成的最大矩形面积。

对于 k 个相邻的元素,我们定义其矩形的最大面积为:

R(k)=kmin(h[i],h[i+1],...,h[i+k1])R(k) = k*min(h[i],h[i+1],...,h[i+k-1])

即,R(k)R(k) 的值为这 kk 个相邻元素中的最小值乘以 kk。现在,小S希望你能帮他找出对于任意 kkR(k)R(k) 的最大值。

测试样例

样例1:

输入: n = 5, array = [1, 2, 3, 4, 5]

输出: 9

样例2:

输入: n = 6, array = [5, 4, 3, 2, 1, 6]

输出: 9

样例3:

输入: n = 4, array = [4, 4, 4, 4]

输出: 16

解题思路

暴力解法:

首先题目很好理解,就是在k个连续的元素里面找到那个最小的元素乘上一个k。然后我们要在诸多这样的值里面找一个最大的。这样就很自然的想到去使用暴力枚举去破解,对于每一位的数字,都遍历一遍他后面的数字,遇到一个情况就更新一次max最后找到最大值。

T(n)=n+(n1)+(n2)++1=n(n+1)2T(n) = n + (n-1) + (n-2) + \ldots + 1 = \frac{n(n+1)}{2}

那么时间复杂度为:O(n2)O(n^2)

并未使用额外数据结构,空间复杂度为O(1):O(1)

def solution(n, array): 
    max_area = 0 

    for i in range(n): 
        min_value = array[i] 
        for j in range(i, n):
            min_value = min(min_value, array[j]) 
            current_area = (j - i + 1) * min_value 
            max_area = max(max_area, current_area) 
return max_area

我们可以考虑使用单调栈的方法来快速确定连续区域的最小值

单调栈解法:

首先来思考一下具体的测试样例,比如[1,2,3,4,5] 在元素1的这个位置时,我们发现1是里面最小的 所以考虑让他最大化 肯定是 1 * 5。

如果在元素2的位置,他的最大宽度就是4 最大化的值就是 2 * 4

依次类推

3 * 3

4 * 2

5 * 1

我们可以发现 他这个宽度的左边界取决于左边有没有比他小的 并且是离这个元素最近的那个位置。

那么又考虑到 我们想要 k个连续数里 最小的那个数乘上一个k

所以宽度的右边界与左边界的寻找相同 即找到他右边比他小的第一个位置。

为了简化计算 我们添加两个虚拟边界 0

那么以h[i]为高度的最大矩形面积就是Areai=h[i]×(right[i]left[i]1) \text{Area}_i = h[i] \times (\text{right}[i] - \text{left}[i] - 1)

def solution(n, heights):

    stack = []  
    max_area = 0
    heights = [0] + heights + [0]
    for i in range(len(heights)):
        # 当当前柱子高度小于栈顶柱子高度时,计算栈顶柱子的面积
        while stack and heights[i] < heights[stack[-1]]:
            height = heights[stack.pop()]  # 栈顶柱子的高度
            width = i - stack[-1] - 1   # 当前柱子与新栈顶之间的宽度
            max_area = max(max_area, height * width)
        stack.append(i)
    
    return max_area

每个数值最多入栈和出栈一次,时间复杂度为 O(n)O(n)

工具的运用

在做这道题的时候,其实我是想都没想直接使用暴力解法的。但是这样的时间复杂度太高了。这里给掘金的刷题提个建议,像leetcode一样告诉我们测试样例的取值范围,时间复杂度太高的不给通过,才能push大家挖掘更好的解法。

那么在我想到这样不行之后,我就询问豆包AI有没有更好的办法。豆包AI会给我提出使用单调栈的建议。那么有了方向后重新思考问题 就可以得出更好的解法了。