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

69 阅读4分钟

题目解析

本题的目标是从一个给定的高度数组中,对于每一个长度为 k 的相邻子数组,计算出其最大矩形面积,最终输出所有可能的 k 中最大矩形面积。

首先,我们需要理解矩形面积的定义。给定一个数组中的一段连续子数组 h[i],h[i+1],,h[i+k1]h[i],h[i+1],…,h[i+k−1],该段子数组的矩形面积可以通过以下公式计算:

R(k)=k×min(h[i],h[i+1],,h[i+k1])R(k)=k×min⁡(h[i],h[i+1],…,h[i+k−1])

其中,k 是当前子数组的长度,min⁡(h[i],h[i+1],…,h[i+k−1])\min(h[i], h[i+1], \dots, h[i+k-1])min(h[i],h[i+1],…,h[i+k−1]) 是该子数组中的最小元素值。

思路分析

我们需要通过穷举所有可能的子数组长度 k 来寻找最大矩形面积。对于每一个长度为 k 的子数组,我们需要找到其最小值,然后计算面积并更新最大值。

  1. 枚举所有可能的子数组长度 k:从 k=1 到 k=n(数组长度),对于每一个 k,我们都要找到所有长度为 k 的子数组。
  2. 计算每个子数组的面积:对于每个子数组,找到它的最小高度,然后根据公式计算面积 R(k)。
  3. 更新最大面积:通过不断比较计算得到的面积,更新最大矩形面积。

解题步骤

  1. 外层循环:遍历所有可能的子数组长度 k,从 1 到 n。
  2. 内层循环:对于每一个 k,遍历所有可能的起点 i,并计算以该起点开始的长度为 k 的子数组的最小值。
  3. 计算面积:计算每个子数组的面积 k×min(h[i],h[i+1],,h[i+k1])k×min⁡(h[i],h[i+1],…,h[i+k−1]),并更新最大面积。

代码详解

def solution(n, array):
    max_area = 0  # 初始化最大面积为 0

    # 遍历所有可能的 k 值
    for k in range(1, n + 1):
        print(f"k={k}")  # 输出当前子数组的长度

        # 遍历数组,计算以每个元素为起点,长度为 k 的子数组的最小值
        for i in range(n - k + 1):
            print(f"i={i}")  # 输出当前子数组的起始位置
            # 计算当前子数组的最小值
            min_height = min(array[i:i + k])
            # 计算当前子数组的面积
            current_area = k * min_height
            # 更新最大面积
            print(f"最大面积:{current_area}")
            max_area = max(max_area, current_area)

    return max_area

if __name__ == "__main__":
    # 测试样例
    print(solution(5, [1, 2, 3, 4, 5]) == 9)  # 预期输出 9

代码分析:

  1. 初始化:首先我们定义一个变量 max_area 来记录当前最大面积。
  2. 外层循环for k in range(1, n + 1),遍历所有可能的子数组长度。
  3. 内层循环for i in range(n - k + 1),遍历每个可能的起始位置 iii,确保子数组的长度不超过数组边界。
  4. 最小值计算min(array[i:i + k]) 用来找出当前子数组中的最小值。
  5. 面积计算:根据公式 k×min(h[i],h[i+1],,h[i+k1])k×min⁡(h[i],h[i+1],…,h[i+k−1]) 计算当前子数组的面积,并更新 max_area
  6. 返回值:最后返回 max_area,即最大矩形面积。

知识总结

在解决这道题的过程中,我总结出了一些关键的知识点:

  1. 滑动窗口的思想:题目要求对每一个长度为 k 的子数组求最小值,并计算矩形面积。虽然本题没有直接使用滑动窗口优化最小值的求解,但这个过程可以使用滑动窗口技术进行优化。
  2. 枚举所有子数组:题目中涉及到的枚举所有长度为 k 的子数组,这样的思路对于很多类似的“区间问题”都可以适用。通过内外层循环嵌套,我们可以遍历所有的子数组。
  3. 时间复杂度优化:虽然本解法的时间复杂度为 O(n3)O(n^3),因为每次都要计算最小值,但在实际问题中,常常可以通过一些优化(如单调栈或滑动窗口)将其优化到 O(n2)O(n^2)O(n)O(n)
  4. 最小值计算:在实际编码时,直接使用 min() 函数来求解子数组的最小值是简洁且易于理解的,但在大规模数据情况下,需要考虑其性能瓶颈。

对其他同学的学习建议

  1. 从简单入手:对于类似的题目,首先可以从暴力解法入手,理解题目和基本的算法思想后,再进行优化。
  2. 理解题目中的定义:这类题目常常会有一些抽象的数学公式或者特殊的定义,理解这些定义对于解决问题至关重要。在本题中,矩形面积的计算公式就是关键。
  3. 优化思维:在暴力解法的基础上,学会寻找优化点。在本题中,如果能使用单调栈来求解最小值,可能会显著提升性能。
  4. 边界情况:一定要注意处理数组的边界情况,例如空数组或者数组长度为1的情况。

通过不断练习和总结,可以在解题过程中发现更多优化的空间,提高自己的编程能力和算法思维。