• Leetcode.2866 美丽塔 II


    题目链接

    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]

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

    • 1 ≤ h e i g h t s [ i ] ≤ m a x H e i g h t s [ i ] 1 \leq heights[i] \leq maxHeights[i] 1heights[i]maxHeights[i]
    • h e i g h t s heights heights 是一个 山状 数组。

    如果存在下标 i i i 满足以下条件,那么我们称数组 h e i g h t s heights heights 是一个 山状 数组:

    • 对于所有 0 < j ≤ i 0 < j \leq i 0<ji ,都有 h e i g h t s [ j − 1 ] ≤ h e i g h t s [ j ] heights[j - 1] \leq heights[j] heights[j1]heights[j]
    • 对于所有 i ≤ k < n − 1 i \leq k < n - 1 ik<n1 ,都有 h e i g h t s [ k + 1 ] ≤ h e i g h t s [ k ] heights[k + 1] \leq heights[k] 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 = m a x H e i g h t s ≤ 1 0 5 1 \leq n = maxHeights \leq 10^5 1n=maxHeights105
    • 1 ≤ m a x H e i g h t s [ i ] ≤ 1 0 9 1 \leq maxHeights[i] \leq 10^9 1maxHeights[i]109

    解法:单调栈 + 前后缀分解

    我们定义 p r e pre pre s u f suf suf

    • 定义 p r e [ i ] pre[i] pre[i] [ 0 , i ] [0 , i] [0,i],以 n u m s [ i ] nums[i] nums[i] 为最大值的 前缀和
    • 定义 s u f [ i ] suf[i] suf[i] [ i , n − 1 ] [i , n - 1] [i,n1],以 n u m s [ i ] nums[i] nums[i] 为最大值的 后缀和

    为了便于我们操作,我们将 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 分别为:

    • p r e = { 0 , 5 , 6 , 10 , 4 , 5 } pre = \{ 0,5,6,10,4,5\} pre={0,5,6,10,4,5}
    • s u f = { 13 , 8 , 6 , 2 , 1 , 0 } suf = \{13,8,6,2,1,0 \} suf={13,8,6,2,1,0}

    那么最大的美丽塔高度和为 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]}(0in)

    现在问题的关键在于如何求出 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=(ij)×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;
        }
    };
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38
    • 39
    • 40
    • 41
    • 42
    • 43
    • 44
  • 相关阅读:
    【面试题精讲】说一说springboot加载配置文件优先级
    ChatGPT新增超强插件:文本直接生成视频、海报,支持自定义修改!
    怎么样做好自己的服务器防御
    python web服务器部署
    【云原生之k8s】K8s 管理工具 kubectl 详解(二)
    java-net-php-python-net本科生毕业设计选导师系统演示录像2019计算机毕业设计程序
    躲避小行星游戏
    AVS3中的intra string copy(ISC)
    海外住宅IP如何助力国外问卷调查?
    Linux内核中ideapad-laptop.c文件全解析6
  • 原文地址:https://blog.csdn.net/m0_74396439/article/details/133778976