Leetcode.2866 美丽塔 II
rating : 2072
给你一个长度为 n n n 下标从 0 0 0 开始的整数数组 m a x H e i g h t s maxHeights maxHeights 。
你的任务是在坐标轴上建 n n n 座塔。第 i i i 座塔的下标为 i i i ,高度为 h e i g h t s [ i ] heights[i] heights[i] 。
如果以下条件满足,我们称这些塔是 美丽 的:
如果存在下标 i i i 满足以下条件,那么我们称数组 h e i g h t s heights heights 是一个 山状 数组:
请你返回满足 美丽塔 要求的方案中,高度和的最大值 。
输入:maxHeights = [5,3,4,1,1]
输出:13
解释:和最大的美丽塔方案为 heights = [5,3,3,1,1] ,这是一个美丽塔方案,因为:
- 1 <= heights[i] <= maxHeights[i]
- heights 是个山状数组,峰值在 i = 0 处。
13 是所有美丽塔方案中的最大高度和。
输入:maxHeights = [6,5,3,9,2,7]
输出:22
解释: 和最大的美丽塔方案为 heights = [3,3,3,9,2,2] ,这是一个美丽塔方案,因为:
- 1 <= heights[i] <= maxHeights[i]
- heights 是个山状数组,峰值在 i = 3 处。
22 是所有美丽塔方案中的最大高度和。
输入:maxHeights = [3,2,5,5,2,3]
输出:18
解释:和最大的美丽塔方案为 heights = [2,2,5,5,2,2] ,这是一个美丽塔方案,因为:
- 1 <= heights[i] <= maxHeights[i]
- heights 是个山状数组,最大值在 i = 2 处。
注意,在这个方案中,i = 3 也是一个峰值。 18 是所有美丽塔方案中的最大高度和。
我们定义 p r e pre pre 和 s u f suf suf:
为了便于我们操作,我们将 p r e pre pre 和 s u f suf suf 都偏移一个长度,即 p r e pre pre 和 s u f suf suf 的长度都为 n + 1 n + 1 n+1。
举例 :
对于 m a x H e i g h t s = [ 5 , 3 , 4 , 1 , 1 ] maxHeights = [5,3,4,1,1] maxHeights=[5,3,4,1,1],则它的 p r e pre pre 和 s u f suf suf 分别为:
那么最大的美丽塔高度和为 m a x { p r e [ i ] + s u f [ i ] } ( 0 ≤ i ≤ n ) max\{ pre[i] + suf[i]\} \quad (0 \leq i \leq n) max{pre[i]+suf[i]}(0≤i≤n)
现在问题的关键在于如何求出 p r e pre pre 和 s u f suf suf。
我们可以使用单调栈。
对于 p r e pre pre ,我们使用一个栈 s t k stk stk,从小到大的记录元素下标 (从栈底到栈顶)。假设当前遍历到的元素为 m a x H e i g h t s [ i ] maxHeights[i] maxHeights[i],并且栈顶元素 大于等于 当前元素,即 m a x H e i g h t s [ s t k . t o p ( ) ] ≥ m a x H e i g h t s [ i ] maxHeights[stk.top()] \geq maxHeights[i] maxHeights[stk.top()]≥maxHeights[i],那么我们就要不断地弹出栈顶元素。
上述操作完成之后,要么栈顶元素小于当前元素,即 m a x H e i g h t s [ s t k . t o p ( ) ] < m a x H e i g h t s [ i ] maxHeights[stk.top()] < maxHeights[i] maxHeights[stk.top()]<maxHeights[i];要么此时栈为空。
我们就设 j j j 为当前的栈顶元素,即 j = s t k . t o p ( ) j = stk.top() j=stk.top();如果栈为空,就设置 j = − 1 j = -1 j=−1。
那么此时 ( j , i ] (j,i] (j,i] 这一区间的值都应该是 m a x H e i g h t s [ i ] maxHeights[i] maxHeights[i],总和就是 s u m = ( i − j ) × m a x H e i g h t s [ i ] sum = (i - j) \times maxHeights[i] sum=(i−j)×maxHeights[i]。
所以此时 p r e [ i ] = s u m + p r e [ j ] pre[i] = sum + pre[j] pre[i]=sum+pre[j]。
对于求 s u f suf suf 也是同理。
时间复杂度: O ( n ) O(n) O(n)
C++代码:
using LL = long long;
class Solution {
public:
long long maximumSumOfHeights(vector<int>& nums) {
int n = nums.size();
vector<LL> pre(n + 1) , suf(n + 1);
stack<int> stk{{-1}};
for(int i = 0;i < n;i++){
while(stk.size() > 1 && nums[stk.top()] >= nums[i]){
stk.pop();
}
int j = stk.top();
pre[i + 1] += (i - j) * 1LL * nums[i];
pre[i + 1] += pre[j + 1];
stk.push(i);
}
//清空栈
while(!stk.empty()) stk.pop();
stk.push(n);
for(int i = n - 1;i >= 0;i--){
while(stk.size() > 1 && nums[stk.top()] >= nums[i]){
stk.pop();
}
int j = stk.top();
suf[i] += (j - i) * 1LL * nums[i];
suf[i] += suf[j];
stk.push(i);
}
LL ans = 0;
for(int i = 0;i <= n;i++){
ans = max(pre[i] + suf[i] , ans);
}
return ans;
}
};