C++ 中使用线段树查找直方图中最大矩形面积

17 Mar 2025 | 4 分钟阅读

直方图是计算机科学中一种重要的数据结构,具有多种用途,包括数据分析和图像处理。确定直方图中的最大矩形区域是一个经常遇到的挑战。在这篇文章中,我们将研究一种使用 C++ 线段树数据结构处理此问题的快速有效方法。

理解问题

考虑一个显示数据频率或分布的条形图,称为直方图。在这里,我们的目标是确定可以在其中构建的最大矩形区域。在直方图中,每个条形图都有特定的高度,并且高度大于或等于当前条形图高度的相邻条形图定义了矩形区域的宽度。

1. 朴素方法

将直方图中的每个条形图视为矩形区域开始的可能位置,是解决此问题的一种简单方法。我们将空间向左和向右扩展每个条形图,直到遇到一个高度较低的条形图。在每个阶段,我们计算面积并记录发现的最大面积。

  • 对于大型直方图,此策略由于其 O(n^2) 的时间复杂度而效率低下,其中 'n' 是直方图中的条形图数量。
  • 我们可以利用线段树(一种常用于范围查询问题的灵活数据结构)来有效地发现直方图中的最大矩形区域。以下是有效方法的运作方式:

使用线段树的有效方法

  • 首先,根据直方图的高度创建线段树。
  • 接下来,从左到右遍历直方图,找到每个条形图左侧和右侧第一个高度较低的条形图。
  • 之后,根据步骤 2 中确定的位置,确定可以使用当前条形图构建的矩形区域的最小高度和宽度。
  • 记录遍历过程中发现的最大面积。

程序

让我们举一个例子来确定使用 C++ 中的线段树在直方图中的最大矩形区域。

输出

Largest Rectangular Area in Histogram using Segment Tree in C++

代码解释

  1. 直方图迭代
    在此示例中,我们从左到右循环遍历直方图中的每个条形图。
  2. 条形图索引堆栈
    我们将条形图索引以高度升序保存在一个堆栈中,这可以通过向量或其他类似数据结构实现。
  3. 保持堆栈完整
    我们决定何时从堆栈中弹出条形图索引以及何时在遍历直方图时将其推入堆栈。
  4. 将条形图索引压入堆栈
    当我们遇到一个高度大于或等于堆栈顶部条形图的条形图时(或者如果堆栈为空),我们将当前条形图的索引压入堆栈。
    通过这样做,可以保证堆栈保留可能有助于创建更大矩形的条形图索引。
  5. 从堆栈中弹出条形图
    每当我们遇到一个高度小于堆栈顶部条形图的条形图时,我们就会开始从堆栈中弹出条形图。
    我们通过测量其高度和宽度(当前位置与堆栈顶部之间的差值)来确定每个弹出的条形图可以形成的面积。
  6. 最大面积更新
    如果计算出的面积大于当前最大值,我们会在计算每个弹出条形图的面积时更新最大面积。
  7. 重复该过程
    直到我们到达直方图的末尾或遇到一个高度低于堆栈顶部条形图的条形图,我们才会继续推入和弹出条形图。
  8. 堆栈中剩余的条形图
    在处理完直方图中的每个条形图后,堆栈中可能还会剩下一些条形图。
    我们继续弹出条形图并计算面积,直到堆栈为空。
  9. 最大面积
    在此操作期间遇到的最大面积是直方图中可以形成的最大矩形区域。

下一个主题C++ async await