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

134 阅读5分钟

题目信息

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

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

R(k)=k×min(h[i],h[i+1],...,h[i+k−1])

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

  • 豆包分析题目

这里我们先让豆包帮我们阅读一下题目

题目理解

  1. 数组高度:给定一个数组 array,每个元素代表某种高度。
  2. 矩形面积:对于任意 k 个相邻的元素,矩形的最大面积为 k * min(h[i], h[i + 1], ..., h[i + k - 1])。
  3. 目标:找出对于所有可能的 k,R(k) 的最大值。

示例解释

  • 样例1:n = 5, array = [1, 2, 3, 4, 5]

    • 对于 k = 3,例如 [3, 4, 5],最小值为3,面积为 3 * 3 = 9。
    • 最大面积为 9。
  • 样例2:n = 6, array = [5, 4, 3, 2, 1, 6]

    • 对于 k = 3,例如 [5, 4, 3],最小值为 3,面积为 3 * 3 = 9。
    • 最大面积为 9。
  • 样例3:n = 4, array = [4, 4, 4, 4]

    • 对于 k = 4,最小值为 4,面积为 4 * 4 = 16。
    • 最大面积为 16

这里有三种思路:

  1. 暴力

初始化变量 result 为 0,用于存储最终要返回的最大乘积值。 这个外层循环控制子数组的长度i,从 1 开始到n(包括n),这样可以遍历所有可能的子数组长度。 这个内层循环控制子数组的起始位置j。n - i + 1是为了确保子数组不超出原始数组的范围。 对于每个可能的子数组(从位置j开始,长度为i),计算子数组长度i与子数组中最小元素的乘积,并与当前的最大乘积值result进行比较,取较大值更新result。返回找到的最大乘积值。

  1. 以每个位置为中心,分别向左右两侧散开,找到最大的面积

定义了一个名为solution的函数,接收两个参数n和array,n可能表示数组的长度,array是要进行处理的数组。 初始化变量max_area为 0,用于存储最终要返回的最大矩形面积值。 这个循环遍历数组中的每个元素。 分别初始化左右指针为当前元素的位置。 这个循环向左查找第一个小于当前元素的位置。如果left不等于 -1(表示没有超出数组范围)且当前位置的元素大于等于正在处理的元素array[i],则继续向左移动指针。 这个循环向右查找第一个小于当前元素的位置。如果right不等于n(表示没有超出数组范围)且当前位置的元素大于等于正在处理的元素array[i],则继续向右移动指针。 计算以当前元素为高度的矩形面积,即当前元素的值array[i]乘以左右指针之间的宽度(right - left - 1),并与当前最大矩形面积max_area进行比较,取较大值更新max_area。

3.单调栈,这个问题可以看作是 leetcode84题"柱状图中最大矩形面积" 问题的一个变种

目标:对每个元素 h[i],找到它作为最小高度时可以形成的最大矩形面积。矩形宽度取决于它的左右边界,即从它开始延伸到左侧和右侧比它高或等于它的最近元素位置。

使用单调栈:我们可以使用单调栈来快速找到每个元素的左右边界。

左边界:对于每个元素,找到左侧第一个小于它的元素位置。

右边界:对于每个元素,找到右侧第一个小于它的元素位置。

矩形面积计算:在找到左右边界后,对于每个元素 h[i],矩形的宽度为 right[i] - left[i] - 1,高度为 h[i]h[i]h[i]。然后计算矩形面积为 height * width。

我们顺带看看是什么一个解题的方法 84. 柱状图中最大的矩形


def solution(n, array):
    # Edit your code here
    
    left = [-1] * n
    stack = []
    
    for i in range(n):
        while stack and array[stack[-1]] >= array[i]:
            stack.pop()
        left[i] = stack[-1] if stack else -1
        stack.append(i)
    
   
    right = [n] * n
    stack = []
    
    for i in range(n - 1, -1, -1):
        while stack and array[stack[-1]] >= array[i]:
            stack.pop()
        right[i] = stack[-1] if stack else n
        stack.append(i)
    
   
    max_area = 0
    for i in range(n):
        height = array[i]
        width = right[i] - left[i] - 1
        max_area = max(max_area, height * width)
    
    return max_area

  1. 确定左边界和右边界的循环至关重要,因为它们准确地确定了以每个元素为高度的矩形在左右方向上能够延伸的最远位置。 在计算右边界的循环中,采用类似的方法从数组的末尾开始遍历,找到每个元素向右能够延伸到的最远位置。

  2. 有了准确的左边界和右边界,才能在后续的循环中计算以每个元素为高度的矩形面积。

  3. 如果没有这两个关键步骤准确地确定左边界和右边界,就无法正确计算出每个元素作为矩形高度时的最大矩形面积,也就无法得到整个数组中的最大矩形面积。