题目
给你一个长度为 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
思路
1、遍历
这个就遍历每个数字,然后选择两个指针向两边移动就可以了,遇到比当前val小的上限就更新。
时间复杂度是O(n^2),空间复杂度是O(1);
2、(官方给的)单调栈 代码2
没看懂,但是时间复杂度是On,空间是O1,我去学下。
------------------------------------01.25补充----------------------------------
假如不用单调栈,仅用一个标识记录从前到后和从后到前的过程中最小值,
循环采用:
for (int i = 1; i < maxHeightsSize; i++)
{
if(maxHeights[i] >= upmin)
{
up[i] = up[i - 1] + maxHeights[i];
}
else
{
up[i] = maxHeights[i] * (i + 1);
upmin = maxHeights[i];
}
}
就会出现一个问题:
测试数据:【5,3,4,1,1】
从前向后遍历的变化趋势是
up【0,0,0,0,0】upmin:0
up【5,0,0,0,0】upmin;5
up【5,3*2,0,0,0】upmin:3
up【5,3*2,3*2 + 4,0,0】upmin:3
up【5,3*2,3*2 + 4,1*4,0】upmin:1
up【5,3*2,3*2 + 4,1*4,1*4+1】upmin:1
这样看上去好像没问题,但是看到down数组的时候就会发现问题了
for (int i = maxHeightsSize - 2; i > 0; i--)
{
if(maxHeights[i] >= downmin)
{
down[i] = down[i + 1] + maxHeights[i];
}
else
{
down[i] = maxHeights[i] * (maxHeightsSize - i);
downmin = maxHeights[i];
}
result = (result > (up[i] + down[i] - maxHeights[i]) ? result : (up[i] + down[i] - maxHeights[i]));
}
down【0,0,0,0,0】downmin:0
down【0,0,0,0,1】downmin:1
down【0,0,0,1+1,1】downmin:1
down【0,0,2+4,1+1,1】downmin:1
就在这一步,此时maxHeights[i] = 3,如果此时使用了单调栈,应该是4弹出,3入栈,此时就可以记录当时的down[i] 正确计算down[1],但是由于没有使用单调栈,此时的最小值信息由于3<4而被强刷成了3,此时按照错误逻辑,down[1]会被刷新成3*4 = 12,正确应该是 3+3+1+1=8,就会出现错误。
代码
1、
#include <stdlib.h>
#include <stdio.h>
typedef struct
{
int* p;
int val;
}point_t;
long long maximumSumOfHeights(int* maxHeights, int maxHeightsSize){
printf("maxHeightsSize = %d\n",maxHeightsSize);
point_t left,right,midium;
long long maxsum = 0;
for (int i = 0; i < maxHeightsSize; i++)
{
long long tmp = 0;
left.p = &(maxHeights[i]);
right.p = &(maxHeights[i]);
midium.p = &(maxHeights[i]);
left.val = maxHeights[i];
right.val = maxHeights[i];
midium.val = maxHeights[i];
tmp += midium.val;
while(left.p > maxHeights)
{
left.p--;
if (*(left.p) < left.val)
{
left.val = *(left.p);
}
tmp += left.val;
}
while(right.p < maxHeights + maxHeightsSize - 1)
{
right.p++;
if (*(right.p) < right.val)
{
right.val = *(right.p);
}
tmp += right.val;
}
if (tmp > maxsum) maxsum = tmp;
}
return maxsum;
}
int main(void)
{
int a[] = {5,3,4,1,1};
long long rc = maximumSumOfHeights(a,(sizeof(a) / sizeof(int)));
printf("rc = %lld\n",rc);
}
代码2:
int n = maxHeightsSize;
long long res = 0;
long long prefix[n], suffix[n];
int stack1[n], stack2[n];
int top1 = 0, top2 = 0;
long long maximumSumOfHeights(int* maxHeights, int maxHeightsSize) {
int n = maxHeightsSize;
long long res = 0;
long long prefix[n], suffix[n];
int stack1[n], stack2[n];
int top1 = 0, top2 = 0;
for (int i = 0; i < n; i++) {
while (top1 > 0 && maxHeights[i] < maxHeights[stack1[top1 - 1]]) {
top1--;
}
if (top1 == 0) {
prefix[i] = (long long)(i + 1) * maxHeights[i];
} else {
prefix[i] = prefix[stack1[top1 - 1]] + (long long)(i - stack1[top1 - 1]) * maxHeights[i];
}
stack1[top1++] = i;
}
for (int i = n - 1; i >= 0; i--) {
while (top2 > 0 && maxHeights[i] < maxHeights[stack2[top2 - 1]]) {
top2--;
}
if (top2 == 0) {
suffix[i] = (long long)(n - i) * maxHeights[i];
} else {
suffix[i] = suffix[stack2[top2 - 1]] + (long long)(stack2[top2 - 1] - i) * maxHeights[i];
}
stack2[top2++] = i;
res = fmax(res, prefix[i] + suffix[i] - maxHeights[i]);
}
return res;
}
int main(void)
{
int a[] = {6,5,3,9,2,7};
int len = sizeof(a) / sizeof(a[0]);
long long result = maximumSumOfHeights(a,len);
printf("ret = %d\n",result);
}
以下是总体调试代码:
long long maximumSumOfHeights(int* maxHeights, int maxHeightsSize) {
int n = maxHeightsSize;
long long res = 0;
long long prefix[n], suffix[n];
int stack1[n], stack2[n];
int top1 = 0, top2 = 0;
for (int i = 0; i < n; i++) {
while (top1 > 0 && maxHeights[i] < maxHeights[stack1[top1 - 1]]) {
top1--;
}
if (top1 == 0) {
prefix[i] = (long long)(i + 1) * maxHeights[i];
} else {
prefix[i] = prefix[stack1[top1 - 1]] + (long long)(i - stack1[top1 - 1]) * maxHeights[i];
}
stack1[top1++] = i;
}
for (int i = n - 1; i >= 0; i--) {
while (top2 > 0 && maxHeights[i] < maxHeights[stack2[top2 - 1]]) {
top2--;
}
if (top2 == 0) {
suffix[i] = (long long)(n - i) * maxHeights[i];
} else {
suffix[i] = suffix[stack2[top2 - 1]] + (long long)(stack2[top2 - 1] - i) * maxHeights[i];
}
stack2[top2++] = i;
res = fmax(res, prefix[i] + suffix[i] - maxHeights[i]);
}
return res;
}
int main(void)
{
int a[] = {6,5,3,9,2,7};
int len = sizeof(a) / sizeof(a[0]);
long long result = maximumSumOfHeights(a,len);
printf("ret = %d\n",result);
}
附上官方题解:
long long maximumSumOfHeights(int* maxHeights, int maxHeightsSize) {
int n = maxHeightsSize;
long long res = 0;
long long prefix[n], suffix[n];
int stack1[n], stack2[n];
int top1 = 0, top2 = 0;
for (int i = 0; i < n; i++) {
while (top1 > 0 && maxHeights[i] < maxHeights[stack1[top1 - 1]]) {
top1--;
}
if (top1 == 0) {
prefix[i] = (long long)(i + 1) * maxHeights[i];
} else {
prefix[i] = prefix[stack1[top1 - 1]] + (long long)(i - stack1[top1 - 1]) * maxHeights[i];
}
stack1[top1++] = i;
}
for (int i = n - 1; i >= 0; i--) {
while (top2 > 0 && maxHeights[i] < maxHeights[stack2[top2 - 1]]) {
top2--;
}
if (top2 == 0) {
suffix[i] = (long long)(n - i) * maxHeights[i];
} else {
suffix[i] = suffix[stack2[top2 - 1]] + (long long)(stack2[top2 - 1] - i) * maxHeights[i];
}
stack2[top2++] = i;
res = fmax(res, prefix[i] + suffix[i] - maxHeights[i]);
}
return res;
}
作者:力扣官方题解
链接:https://leetcode.cn/problems/beautiful-towers-i/solutions/2614597/mei-li-ta-i-by-leetcode-solution-uqnf/
来源:力扣(LeetCode)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。