问题重述
给定一个高度数组 h1, h2, ..., hN,需要计算对于任意 k 个相邻元素,它们所能形成的最大矩形面积。具体地,对于任意 k 个相邻元素,矩形的最大面积定义为 k 乘以这 k 个元素中的最小值。小S希望找出对于所有可能的 k 值,这个最大矩形面积 R(k) 的最大值。
代码分析
def solution(n, array):
result = 0
for k in range(1, n + 1):
for i in range(n - k + 1):
temp = solution2(k, array, i)
if temp > result:
result = temp
return result
def solution2(k, array, i):
min_value = float('inf')
for j in range(k):
if array[i + j] < min_value:
min_value = array[i + j]
return min_value * k
if __name__ == "__main__":
# Add your test cases here
print(solution(5, [1, 2, 3, 4, 5]) == 9)
-
函数
solution(n, array):- 这个函数接受数组的长度
n和数组array作为输入。 - 它通过两层循环遍历所有可能的
k值(从 1 到n)和所有可能的起始索引i(从 0 到n - k)。 - 对于每个
k和i,它调用solution2(k, array, i)来计算当前k个相邻元素能形成的最大矩形面积。 - 它更新
result变量以保存遇到的最大面积。
- 这个函数接受数组的长度
-
函数
solution2(k, array, i):- 这个函数接受
k、数组array和起始索引i作为输入。 - 它遍历从
i到i + k - 1的元素,找到这些元素中的最小值。 - 它返回这个最小值乘以
k,即当前k个相邻元素能形成的最大矩形面积。
- 这个函数接受
优化分析
原始代码存在的问题
- 时间复杂度:原始代码的时间复杂度是 O(n^3),因为它有三层嵌套循环:外层循环遍历
k,中间层循环遍历起始索引i,内层循环计算k个元素中的最小值。 - 重复计算:原始代码在每次计算
R(k)时都会重新计算最小值,这是不必要的,并且导致了大量的重复计算。 - 效率低下:由于时间复杂度高和重复计算,原始代码在处理大型数组时会变得非常慢。
优化后的代码如下所示
def solution(n, array):
# Initialize an array to hold the contribution of each element
contribution = [0] * n
# Previous smaller element index
prev_smaller = [-1] * n
# Next smaller element index
next_smaller = [n] * n
# Fill prev_smaller
stack = []
for i in range(n):
while stack and array[stack[-1]] >= array[i]:
stack.pop()
prev_smaller[i] = stack[-1] if stack else -1
stack.append(i)
# Clear stack for next smaller
stack = []
for i in range(n - 1, -1, -1):
while stack and array[stack[-1]] > array[i]:
stack.pop()
next_smaller[i] = stack[-1] if stack else n
stack.append(i)
# Now calculate the contribution of each element
for i in range(n):
left_count = i - prev_smaller[i]
right_count = next_smaller[i] - i
contribution[i] = array[i] * left_count * right_count
# The result is the maximum contribution
return max(contribution)
if __name__ == "__main__":
# Add your test cases here
print(solution(5, [1, 2, 3, 4, 5]) == 9)
优化代码分析
优化代码使用了单调栈的概念来预处理每个元素左侧和右侧第一个比它小的元素的位置。然后,它利用这些信息来计算每个元素作为矩形高度时能够形成的最大面积,并返回这些面积中的最大值。
- 时间复杂度:优化代码的时间复杂度是 O(n),因为它只需要两次线性扫描来填充
prev_smaller和next_smaller数组,以及一次线性扫描来计算每个元素的贡献。 - 空间复杂度:空间复杂度也是 O(n),因为需要额外的数组来存储每个元素的左侧和右侧较小元素的索引,以及每个元素的贡献。
- 效率:与原始代码相比,优化代码显著提高了效率,因为它避免了嵌套循环和重复计算最小值。
总结
上述代码定义了一个函数solution,用于计算给定数组中以每个元素为高的最大矩形面积,并返回最大面积值。它利用单调栈预处理每个元素的左右较小元素索引,然后计算每个元素的贡献(即以其为高的最大矩形面积),最后返回贡献中的最大值。