返回

剖析LeetCode 84、Poj 2559和hdu 1506:柱状图中的最大矩形

闲谈

1. 问题概述:柱状图中的最大矩形

给定一个包含非负整数的柱状图,每个柱状图的宽度为1,我们需要找到柱状图中最大的矩形面积。

2. 循环方法:两次循环

最直观的解决方法是使用两次循环。外层循环遍历柱状图的每个柱子,内层循环遍历该柱子右侧的所有柱子,计算它们所能构成的矩形面积。如果某个柱子右侧没有其他柱子,那么它构成的矩形面积就等于其高度。

3. 循环方法:单调栈

为了优化循环方法,我们可以利用栈来记录柱子的高度。当我们遍历柱状图时,将每个柱子的高度入栈。如果当前柱子的高度大于栈顶元素的高度,那么栈顶元素构成的矩形面积就是最大矩形面积。将栈顶元素出栈,并以当前柱子为右边界计算矩形面积。

如果当前柱子的高度小于或等于栈顶元素的高度,那么我们将继续入栈,直到遇到一个高度较小的柱子。当遇到高度较小的柱子时,栈顶元素构成的矩形面积就是最大矩形面积。将栈顶元素出栈,并以当前柱子为右边界计算矩形面积。

4. 动态规划:一维数组

我们可以使用一维数组来存储每个柱子构成的最大矩形面积。假设数组dp[i]表示柱状图中第i个柱子构成的最大矩形面积,那么我们可以通过以下递推公式计算dp[i]:

dp[i] = max(dp[i], dp[i-1] + height[i])

其中height[i]表示第i个柱子的高度。这个递推公式表示第i个柱子构成的最大矩形面积要么是它自身构成的矩形面积,要么是它与左侧柱子构成的矩形面积加上它自身构成的矩形面积。

5. 代码示例

def largest_rectangle_area(heights):
    stack = []
    max_area = 0

    for i, height in enumerate(heights):
        while stack and height < heights[stack[-1]]:
            h = heights[stack.pop()]
            w = i if not stack else i - stack[-1] - 1
            max_area = max(max_area, h * w)
        stack.append(i)

    while stack:
        h = heights[stack.pop()]
        w = len(heights) if not stack else len(heights) - stack[-1] - 1
        max_area = max(max_area, h * w)

    return max_area

def largest_rectangle_area_dp(heights):
    n = len(heights)
    dp = [0] * n
    dp[0] = heights[0]

    for i in range(1, n):
        dp[i] = heights[i]
        if heights[i] < heights[i-1]:
            dp[i] = dp[i-1] + heights[i]

    max_area = max(dp)
    return max_area

6. 图示说明

图中给出了一个柱状图的例子,柱状图的高度分别为[2, 1, 5, 6, 2, 3]。使用循环方法可以计算出柱状图中最大的矩形面积为10,使用动态规划方法也可以计算出柱状图中最大的矩形面积为10。

7. 总结

在这篇文章中,我们介绍了LeetCode 84、Poj 2559和hdu 1506这三个题目的解题思路。我们从两个方向的循环方法开始,然后介绍了如何使用栈来优化算法。此外,我们还探讨了动态规划的解决方法,并提供了清晰的代码示例和详细的图示说明。希望这篇文章能够帮助您透彻理解这些问题的解决方案。