leetcode 2865. 美丽塔 I

题目

给你一个长度为 n 下标从 0 开始的整数数组 maxHeights 。

你的任务是在坐标轴上建 n 座塔。第 i 座塔的下标为 i ,高度为 heights[i] 。

如果以下条件满足,我们称这些塔是 美丽 的:

  1. 1 <= heights[i] <= maxHeights[i]
  2. 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)
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

结果

  • 14
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值