2865. 美丽塔 I
1.题目介绍
给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。
你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i ,高度为 heights[i] 。
如果以下条件满足,我们称这些塔是 美丽 的:
1 <= heights[i] <= maxHeights[i]
heights 是一个 山脉 数组。
如果存在下标 i 满足以下条件,那么我们称数组 heights 是一个 山脉 数组:
-对于所有 0 < j <= i ,都有 heights[j - 1] <= heights[j]
-对于所有 i <= k < n - 1 ,都有 heights[k + 1] <= heights[k]
-请你返回满足 美丽塔 要求的方案中,高度和的最大值 。
示例 1:
输入:maxHeights = [5,3,4,1,1]
输出:13
解释:和最大的美丽塔方案为 heights = [5,3,3,1,1] ,这是一个美丽塔方案,因为:
- 1 <= heights[i] <= maxHeights[i]
- heights 是个山脉数组,峰值在 i = 0 处。
13 是所有美丽塔方案中的最大高度和。
示例 2:
输入:maxHeights = [6,5,3,9,2,7]
输出:22
解释: 和最大的美丽塔方案为 heights = [3,3,3,9,2,2] ,这是一个美丽塔方案,因为:
- 1 <= heights[i] <= maxHeights[i]
- heights 是个山脉数组,峰值在 i = 3 处。
22 是所有美丽塔方案中的最大高度和。
示例 3:
输入: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 是所有美丽塔方案中的最大高度和。
提示:
1 <= n == maxHeights <= 103
1 <= maxHeights[i] <= 109
2.题解
2.1 暴力枚举
思路
只要弄懂题目的意思,知道所谓美丽塔,就是选中某一个i作为最高点,向两边逐渐递减降低即可知道如何枚举
类似:
所以枚举所有点作为最高点的情况,从最高点开始,向左向右,要么是小于记录值,保留自身,更新记录值;要么大于记录值,大小改变为记录值,求和。
取其中最大的情况。
代码
class Solution {
public:
long long maximumSumOfHeights(vector<int>& maxHeights) {
int n = maxHeights.size();
long long ans = 0;
for(int i = 0; i < n; i++){
int temp = maxHeights[i];
long long sum = temp;
for(int j = i - 1; j >= 0; j--){
sum += min(temp, maxHeights[j]);
temp = min(temp, maxHeights[j]);
}
temp = maxHeights[i];
for(int k = i + 1; k < n; k++){
sum += min(temp, maxHeights[k]);
temp = min(temp, maxHeights[k]);
}
ans = max(sum, ans);
}
return ans;
}
};
复杂度分析
时间复杂度:O(n^2),其中 n 表示给定数组的长度。枚举山状数组的最大值需要的时间为 O(n),给定最大值求数组元素的和需要的时间为 O(n)
空间复杂度:O(1)。
2.2 单调栈
思路
大概思路类似如下图,这里的单调栈存的是对应的索引值而不是具体的数组值,如果遇到当前值小于栈中索引对应数组值,则不断出栈,直到单调为止
这里同时记录了所有情况的最大和,prefix(i)表示的是从0到顶峰i(也就是左端单调的最大和),suffix(i)表示的是从顶峰i到n-1(也就是右端单调的最大和)
最终和为prefix(i) + suffix(i) - maxHeights[i] 重复加了一次。
枚举不同的i值,最终取得其中的最大值。
这里我们可以通过类似前缀和的思路,利用之前算得的单调栈头部索引对应的最大和 与 单调栈头部索引到当前索引距离*当前数组值(这些存在着大于当前数组值的情况,所以被事先出栈,一律计算为当前数组值)
代码
class Solution {
public:
long long maximumSumOfHeights(vector<int>& maxHeights) {
int n = maxHeights.size();
long long ans = 0;
vector<long long> prefix(n), suffix(n);
stack<int> stk1, stk2;
for(int i = 0; i < n; i++){
while(!stk1.empty() && maxHeights[i] < maxHeights[stk1.top()]){
stk1.pop();
}
if(stk1.empty()) prefix[i] = (long long)(i - 0 + 1) * maxHeights[i]; //种树问题,总数等于差值+1
else{
prefix[i] = prefix[stk1.top()] + (long long)(i - stk1.top()) * maxHeights[i]; //这里不计算stk1.top()那个索引对应值,所以不加1
}
stk1.emplace(i);
}
for(int i = n - 1; i >= 0; i--){
while(!stk2.empty() && maxHeights[i] < maxHeights[stk2.top()]){
stk2.pop();
}
if(stk2.empty()) suffix[i] = (long long)(n - 1 - i + 1) * maxHeights[i];
else{
suffix[i] = suffix[stk2.top()] + (long long)(stk2.top() - i) * maxHeights[i];
}
stk2.emplace(i);
ans = max(ans, prefix[i] + suffix[i] - maxHeights[i]);
}
return ans;
}
};
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 记一次.NET内存居高不下排查解决与启示
· DeepSeek 开源周回顾「GitHub 热点速览」
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了