最大矩形面积的算法问题
一、问题理解
1. 问题描述
- 给定一个数组 h ,数组中的每个元素代表某种高度。
- 对于任意选择的 k 个相邻元素,定义其矩形的最大面积为 R(k)=k×min(h[i],h[i + 1],...,h[i + k - 1]) ,即这 k 个相邻元素中的最小值乘以 k 。
- 需要找出对于任意 k , R(k) 的最大值。
2. 测试样例分析
- 样例1:
- 输入: n = 5, array = [1, 2, 3, 4, 5]
- 输出: 9
- 分析:这里 n = 5 表示数组长度为5。当 k = 3 时,选择 [3, 4, 5] 这3个相邻元素,最小值是3, R(3)=3×3 = 9 ,这是该数组能得到的最大 R(k) 值。
- 样例2:
- 输入: n = 6, array = [5, 4, 3, 2, 1, 6]
- 输出: 9
- 分析:当 k = 3 时,选择 [3, 2, 1] 这3个相邻元素,最小值是1, R(3)=3×3 = 9 ,这是该数组能得到的最大 R(k) 值。
- 样例3:
- 输入: n = 4, array = [4, 4, 4, 4]
- 输出: 16
- 分析:当 k = 4 时,选择 [4, 4, 4, 4] 这4个相邻元素,最小值是4, R(4)=4×4 = 16 ,这是该数组能得到的最大 R(k) 值。
二、解题思路
1. 暴力解法(Brute - Force)
- 双重循环:
- 外层循环遍历 k 从1到 n ( k 表示选择的相邻元素个数)。
- 内层循环遍历数组,每次选择 k 个相邻元素,计算 R(k) 的值。
- 在每次计算 R(k) 时,找到这 k 个元素中的最小值,然后计算 k 乘以最小值。
- 更新全局最大的 R(k) 值。
- 时间复杂度:
- 外层循环执行 n 次,内层循环对于每个 k 最多执行 n - k + 1 次。对于每次内层循环,还需要找到 k 个元素中的最小值,这需要 O(k) 时间。
- 总的时间复杂度为O(n^3),因为\sum_{k = 1}^{n}(n - k + 1)×k=\sum_{k = 1}^{n}(nk - k^2 + k)=O(n^3)。
2. 优化解法 - 单调栈(Monotonic Stack)
- 思路:
- 利用单调栈来解决这个问题。单调栈是一种特殊的数据结构,栈内元素保持单调递增或单调递减的顺序。
- 对于这个问题,可以把数组中的每个元素看作一个矩形的高度,通过单调栈来找到每个元素左右两侧第一个比它小的元素的位置。
- 步骤:
- 从左到右遍历数组,对于每个元素:
- 如果栈为空或者当前元素大于等于栈顶元素,则将当前元素的索引入栈。
- 如果当前元素小于栈顶元素,则不断弹出栈顶元素,直到栈为空或者栈顶元素小于当前元素。
- 对于每次弹出的栈顶元素,计算以它为最小高度的矩形的面积。矩形的宽度可以通过当前元素的索引和栈顶下一个元素的索引来确定(如果栈为空,则宽度为当前元素的索引;如果栈顶下一个元素存在,则宽度为当前元素的索引减去栈顶下一个元素的索引再减1)。
- 同样地,从右到左再遍历一次数组,重复上述过程。
- 时间复杂度:
- 每个元素最多进栈和出栈一次,所以时间复杂度为O(n),其中 n 是数组的长度。
三、代码实现(以优化解法 - 单调栈为例)
def largestRectangleArea(heights): heights.append(0) # 为了处理最后一个元素,添加一个高度为0的元素 stack = [] max_area = 0 for i, h in enumerate(heights): while stack and heights[stack[-1]] > h: height = heights[stack.pop()] width = i if not stack else i - stack[-1] - 1 max_area = max(max_area, height * width) stack.append(i) return max_area
1. 函数定义
- 定义函数 largestRectangleArea ,参数为 heights (表示高度数组)。 2. 初始化
- 在高度数组末尾添加一个高度为0的元素,这样可以确保栈中的所有元素都能被处理。
- 初始化一个空栈 stack 和最大面积 max_area 为0。
3. 遍历数组
- 遍历高度数组 heights ,对于每个元素:
- 当栈不为空且栈顶元素对应的高度大于当前元素的高度时,不断弹出栈顶元素。
- 对于每次弹出的栈顶元素,计算以它为最小高度的矩形的面积,并更新最大面积 max_area 。
- 矩形的宽度计算方法如上述步骤中所述。
- 将当前元素的索引入栈。
4. 返回结果
- 最后返回最大面积 max_area 。
四、总结
1. 知识点总结
- 单调栈:是一种在算法中常用的数据结构,用于解决一些与区间最值相关的问题。在本题中,通过单调栈可以高效地找到每个元素左右两侧第一个比它小的元素的位置,从而计算出以该元素为最小高度的矩形的最大面积。
- 算法优化:从暴力解法的O(n^3)时间复杂度优化到单调栈解法的O(n)时间复杂度,展示了如何通过选择合适的数据结构和算法来提高解题效率。
2. 学习建议
- 对于初学者:
- 首先理解问题的本质,明确需要解决的问题是什么。在本题中,就是要找到通过选择相邻元素形成的矩形的最大面积。
- 尝试从暴力解法入手,虽然暴力解法的时间复杂度可能很高,但它有助于理解问题的解决过程。
- 学习和掌握数据结构和算法的基本概念,如栈、队列、单调栈、单调队列等,这些数据结构在解决实际问题中非常有用。
- 对于进阶学习者:
- 深入研究各种优化算法,理解它们的原理和应用场景。在本题中,单调栈的应用是一个很好的例子。
- 多做练习题,通过实践来巩固和提高算法和数据结构的应用能力。
- 学习如何分析算法的时间复杂度和空间复杂度,这有助于评估算法的优劣和选择合适的算法来解决问题。