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

45 阅读3分钟

问题重述

给定一个高度数组 h1, h2, ..., hN,需要计算对于任意 k 个相邻元素,它们所能形成的最大矩形面积。具体地,对于任意 k 个相邻元素,矩形的最大面积定义为 k 乘以这 k 个元素中的最小值。小S希望找出对于所有可能的 k 值,这个最大矩形面积 R(k) 的最大值。

代码分析

def solution(n, array):
    result = 0
    for k in range(1, n + 1):
        for i in range(n - k + 1):
            temp = solution2(k, array, i)
            if temp > result:
                result = temp
    return result

def solution2(k, array, i):
    min_value = float('inf')
    for j in range(k):
        if array[i + j] < min_value:
            min_value = array[i + j]
    return min_value * k

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 3, 4, 5]) == 9)
  1. 函数 solution(n, array)

    • 这个函数接受数组的长度 n 和数组 array 作为输入。
    • 它通过两层循环遍历所有可能的 k 值(从 1 到 n)和所有可能的起始索引 i(从 0 到 n - k)。
    • 对于每个 k 和 i,它调用 solution2(k, array, i) 来计算当前 k 个相邻元素能形成的最大矩形面积。
    • 它更新 result 变量以保存遇到的最大面积。
  2. 函数 solution2(k, array, i)

    • 这个函数接受 k、数组 array 和起始索引 i 作为输入。
    • 它遍历从 i 到 i + k - 1 的元素,找到这些元素中的最小值。
    • 它返回这个最小值乘以 k,即当前 k 个相邻元素能形成的最大矩形面积。

优化分析

原始代码存在的问题

  1. 时间复杂度:原始代码的时间复杂度是 O(n^3),因为它有三层嵌套循环:外层循环遍历 k,中间层循环遍历起始索引 i,内层循环计算 k 个元素中的最小值。
  2. 重复计算:原始代码在每次计算 R(k) 时都会重新计算最小值,这是不必要的,并且导致了大量的重复计算。
  3. 效率低下:由于时间复杂度高和重复计算,原始代码在处理大型数组时会变得非常慢。

优化后的代码如下所示

def solution(n, array):
    # Initialize an array to hold the contribution of each element
    contribution = [0] * n

    # Previous smaller element index
    prev_smaller = [-1] * n
    # Next smaller element index
    next_smaller = [n] * n

    # Fill prev_smaller
    stack = []
    for i in range(n):
        while stack and array[stack[-1]] >= array[i]:
            stack.pop()
        prev_smaller[i] = stack[-1] if stack else -1
        stack.append(i)

    # Clear stack for next smaller
    stack = []
    for i in range(n - 1, -1, -1):
        while stack and array[stack[-1]] > array[i]:
            stack.pop()
        next_smaller[i] = stack[-1] if stack else n
        stack.append(i)

    # Now calculate the contribution of each element
    for i in range(n):
        left_count = i - prev_smaller[i]
        right_count = next_smaller[i] - i
        contribution[i] = array[i] * left_count * right_count

    # The result is the maximum contribution
    return max(contribution)

if __name__ == "__main__":
    # Add your test cases here
    print(solution(5, [1, 2, 3, 4, 5]) == 9)

优化代码分析

优化代码使用了单调栈的概念来预处理每个元素左侧和右侧第一个比它小的元素的位置。然后,它利用这些信息来计算每个元素作为矩形高度时能够形成的最大面积,并返回这些面积中的最大值。

  1. 时间复杂度:优化代码的时间复杂度是 O(n),因为它只需要两次线性扫描来填充 prev_smaller 和 next_smaller 数组,以及一次线性扫描来计算每个元素的贡献。
  2. 空间复杂度:空间复杂度也是 O(n),因为需要额外的数组来存储每个元素的左侧和右侧较小元素的索引,以及每个元素的贡献。
  3. 效率:与原始代码相比,优化代码显著提高了效率,因为它避免了嵌套循环和重复计算最小值。

总结

上述代码定义了一个函数solution,用于计算给定数组中以每个元素为高的最大矩形面积,并返回最大面积值。它利用单调栈预处理每个元素的左右较小元素索引,然后计算每个元素的贡献(即以其为高的最大矩形面积),最后返回贡献中的最大值。