问题描述
小S最近在分析一个数组 ℎ1,ℎ2,...,ℎ𝑁,数组的每个元素代表某种高度。小S对这些高度感兴趣的是,当我们选取任意 k 个相邻元素时,如何计算它们所能形成的最大矩形面积。 对于 k 个相邻的元素,我们定义其矩形的最大面积为: 𝑅(𝑘)=𝑘×𝑚𝑖𝑛(ℎ[𝑖],ℎ[𝑖+1],...,ℎ[𝑖+𝑘−1]) 即,R(k) 的值为这 k 个相邻元素中的最小值乘以 k。现在,小S希望你能帮他找出对于任意 k,R(k) 的最大值
测试样例
样例1:
输入:
n = 5, array = [1, 2, 3, 4, 5]
输出:9
样例2:
输入:
n = 6, array = [5, 4, 3, 2, 1, 6]
输出:9
样例3:
输入:
n = 4, array = [4, 4, 4, 4]
输出:16
思路分析
题目要求我们求解任意连续k个元素构成的最大矩形面积,其中面积定义为k乘以这k个元素中的最小值。这个问题可以通过动态规划来解决,关键在于确定初始状态和状态转移方程。
-
初始状态:当k=1时,每个元素自身就是一个矩形,所以初始状态
dp[1][i]等于数组的第i个元素。 -
状态转移:对于长度大于1的区间,它是由前一个区间和当前元素组成的,在这里我们可以通过比较前一个区间的最小值和当前元素来确定当前区间的最小值。状态转移方程可以表示为
dp[len][right] = min(dp[len-1][right-1], array[right]),其中len是区间的长度,right是区间的右端点。 -
优化:- 由于每次状态转移只依赖于前一个状态,我们可以在遍历数组的过程中即时更新
dp[right],而不需要等待整个区间的所有元素都被处理,我们可以将二维的动态规划优化为一维,即dp[right] = min(dp[right-1], array[right]),这样每次只需要更新当前位置的状态,而不需要维护一个完整的二维数组。- 原始的二维动态规划方法需要维护一个
dp[len][right]的二维数组,其中len是区间的长度,right是区间的右端点。这会导致空间复杂度为O(n^2),因为我们需要存储所有可能的区间长度和右端点的组合。 - 通过优化,我们只需要维护一个一维数组
dp[right],它只存储到当前位置为止的最小高度。这样,空间复杂度降低到O(n),因为我们只需要存储与数组长度相同数量的元素。
- 原始的二维动态规划方法需要维护一个
通过这种方式,可以有效地减少空间复杂度,同时保持时间复杂度在可接受的范围内。这种方法的核心在于利用动态规划的思想,通过维护一个一维数组来模拟二维数组的状态转移,从而求解问题。
代码
def solution(n, array):
# Edit your code here
dp = array.copy()
max_v = max(dp)
for i in range(1, n):
max_dp = 0
for j in range(n - 1, i - 1, -1):
dp[j] = min(dp[j - 1], array[j])
max_dp = max(max_dp, dp[j])
max_v = max(max_dp * (i + 1), max_v)
return max_v
复杂度分析
时间复杂度是:O(n^2)
空间复杂度:O(n)