返回

刷题者指南:征服柱状图中最大的矩形(题号84)

前端

在计算机科学领域,算法设计是一门重要的学科,它旨在解决各种各样的计算问题,柱状图中最大的矩形便是其中之一。那么,如何有效地求解这一问题呢?

本文将介绍一种经典的算法——动态规划算法,来解决题号84:柱状图中最大的矩形。动态规划算法是一种自顶向下的递归方法,它将问题分解成较小的子问题,逐步解决并保存子问题的答案,从而达到解决整个问题的目的。

问题概述

给定 n 个非负整数,用来表示柱状图中各个柱子的高度。每个柱子彼此相邻,且宽度为 1。求在该柱状图中,能够勾勒出来的矩形的最大面积。

例如,对于柱状图 [2, 1, 5, 6, 2, 3],最大矩形面积为 10,如下图所示:

  +-------+  
  |       |  
  |   +---+ |  
  |   |   |  
  +---+---+  
     1   5  

算法步骤

1. 初始化

  • 将输入的柱状图看作一个直方图,每个柱子的宽度为1。
  • 定义一个数组 heights 来存储柱状图中每个柱子的高度。
  • 定义一个数组 max_areas 来存储柱状图中每个柱子向左延伸的最大矩形面积。
  • 定义一个栈 stack 来存储柱状图中已经处理过的柱子。

2. 遍历柱状图

  • 对于柱状图中的每个柱子,从左到右依次进行遍历。
  • 如果当前柱子的高度大于等于栈顶柱子的高度,则将其压入栈中。
  • 如果当前柱子的高度小于栈顶柱子的高度,则弹出栈顶柱子,并计算当前柱子向左延伸的最大矩形面积。
  • 将计算出的最大矩形面积存储在 max_areas 数组中。

3. 计算最大矩形面积

  • 遍历完所有柱子后,栈中剩余的柱子都是柱状图中最右边的柱子。
  • 对于栈中的每个柱子,计算其向右延伸的最大矩形面积。
  • 将计算出的最大矩形面积与 max_areas 数组中的最大值进行比较,取较大值作为柱状图中最大的矩形面积。

代码示例

def largest_rectangle_area(heights):
    # 初始化
    max_areas = [0] * len(heights)
    stack = []

    # 遍历柱状图
    for i, height in enumerate(heights):
        # 如果栈为空或当前柱子的高度大于等于栈顶柱子的高度,则将其压入栈中
        if not stack or heights[stack[-1]] <= height:
            stack.append(i)
        # 如果当前柱子的高度小于栈顶柱子的高度,则弹出栈顶柱子,并计算当前柱子向左延伸的最大矩形面积
        else:
            while stack and heights[stack[-1]] > height:
                top = stack.pop()
                # 计算当前柱子向左延伸的最大矩形面积
                max_areas[top] = heights[top] * (i if not stack else i - stack[-1] - 1)
            stack.append(i)

    # 计算栈中剩余柱子的最大矩形面积
    while stack:
        top = stack.pop()
        max_areas[top] = heights[top] * (len(heights) if not stack else len(heights) - stack[-1] - 1)

    # 返回柱状图中最大的矩形面积
    return max(max_areas)

时间复杂度

算法的时间复杂度为 O(n),其中 n 是柱状图中柱子的数量。因为遍历柱状图只需要一次,计算每个柱子向左延伸的最大矩形面积也只需要常数时间,因此总的时间复杂度为 O(n).

总结

动态规划算法是一种强大的算法设计方法,它可以将复杂的问题分解成较小的子问题,逐步解决并保存子问题的答案,从而达到解决整个问题的目的。在柱状图中最大的矩形问题中,动态规划算法能够有效地求解问题,时间复杂度为 O(n).