题目
思路
将第 i
个元素作为山顶时,可以将山脉数组分为山顶左右两个部分。
对于山顶左边部分,确保数组为非递减数组;对于山顶右边部分,确保数组为非递增数组。
设山顶左边部分构成的非递减数组元素和的最大值为prefix[i]
,山顶右边部分构成的非递增数组元素和的最大值为suffix[i]
,则构成的山脉数组的高度和为prefix[i] + suffix[i] - maxHeight[i]
。
接下来,任务变成计算单调数组的和最大值,这里可以使用单调栈,单调栈可以保证栈中数据的单调性。
对于山顶左边部分,我们维护一个单调不减的单调栈,根据单调栈可以计算山顶左边部分构成的非递减数组元素和的最大值,原理如下:
第 i 个元素作为山顶时山顶左侧的最大高度和 = 单调栈栈顶元素 j 作为山顶时山顶左侧的最大高度和 + 单调栈栈顶 j 与第 i 个元素之间的距离 * 山顶高度
如图所示,第 5 个元素作为山顶时,单调栈元素包括第0、2和 3这三个元素,栈顶元素为第 3 个元素。
第 5 个元素作为山顶时山顶左侧的最大高度和 = 第 3 个元素作为山顶时山顶左侧的最大高度和 + 单调栈栈顶与山顶之间的距离(5 - 3 = 2) * 山顶高度
对于山顶右边部分,同理。
代码
```python
class Solution:
def maximumSumOfHeights(self, maxHeights: List[int]) -> int:
n = len(maxHeights)
res = 0
prefix, suffix = [0] * n, [0] * n # 前缀单调栈 和 后缀单调栈
stack1, stack2 = [], []
for i in range(n):
# stack1 非空 且 当前元素小于栈顶元素时,不断弹出栈顶元素
while stack1 and maxHeights[i] < maxHeights[stack1[-1]]:
stack1.pop()
if stack1:
prefix[i] = prefix[stack1[-1]] + (i - stack1[-1]) * maxHeights[i]
else:
prefix[i] = (i + 1) * maxHeights[i]
stack1.append(i) # 添加栈顶元素
for i in range(n - 1, -1, -1):
# stack2 非空 且 当前元素小于栈顶元素时,不断弹出栈顶元素
while stack2 and maxHeights[i] < maxHeights[stack2[-1]]:
stack2.pop()
if stack2:
suffix[i] = suffix[stack2[-1]] + (stack2[-1] - i) * maxHeights[i]
else:
suffix[i] = (n - i) * maxHeights[i]
stack2.append(i) # 添加栈顶元素
res = max(res, prefix[i] + suffix[i] - maxHeights[i])
return res