【每日一题】美丽塔 II

Tag

【单调栈】【数组】【2023-12-21】


题目来源

2866. 美丽塔 II


题目解读

题目意思相对明确,所谓的美丽塔数组就是山状数组,即有一个高度为 maxHeight[i] 的山峰,山峰两侧的高度要小于 maxHeight[i] 并且小于各自的允许高度。需要找出满足以上条件的美丽塔数组,返回数组和。


方法一:暴力枚举

暴力枚举即以每一个整数元素作为山峰,对左右两侧的山峰高度依次处理,取出所有山峰中美丽塔数组的最大值。处理规则如下:

  • 当前的最高山峰下标为 i,此处山峰高度为 maxHeight[i];当前山峰美丽塔的最大值为 res = maxHeight[i]
  • 从下标 i-1 处开始枚举山峰左侧的高度 maxHeight[i-1],如果 maxHeight[i-1] <= maxHeight[i],则下标 i-1 处的山峰高度最大为 maxHeight[i-1],否则下标 i-1 处的山峰高度最大为 maxHeight[i],其实 i-1 处的山峰高度最大为 min(maxHeight[i-1], maxHeight[i])。加到 res 中,枚举完山峰 i 左侧的山,即可得到以下标 i 为山峰的左侧山的高度最大值。
  • 同理,可以得到以下标 i 为山峰的右侧山的高度最大值。
  • 最后,选出枚举所有山峰得到的最大值作为最后的答案。

复杂度分析

时间复杂度: O ( n 2 ) O(n^2) O(n2) n n n 为数组 maxHeight 的长度,对于规模为 1 0 3 10^3 103 甚至 1 0 4 10^4 104 的数据量,该方法可以顺利通过,对于更大规模的数据比如 1 0 5 10^5 105,暴力枚举的方法一定超时,时间复杂度 O ( n ) O(n) O(n) 的解法请看 方法二

空间复杂度: O ( 1 ) O(1) O(1)

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

前、后缀的方法在做题时候想到了,但是一直没想通如何计算前、后缀,经过 前后缀分解+单调栈(Python/Java/C++/Go) 思路点拨之后,豁然开朗。

maxHeight 简化为 nums

我们可以借助前后缀的思想,提前计算山峰左侧的递增段的最大和以及山峰右侧递减段最大和。

我们使用数组 pre[i] 表示山峰 nums[i] 左侧的递增段的最大和,使用数组 suf[i] 表示山峰右侧递减段最大和。那么最终的答案为 pre[i] + suf[i+1] 的最大值。

接下来看一下如何计算数组 presuf

使用单调栈,元素值从栈底到栈顶严格递增。

我们先计算 pre,从左到右遍历数组 nums,设当前的元素和为 sum

  • 如果 nums[i] 大于栈顶元素,直接将 nums[i] 加到 sum 中,同时把 i 入栈(栈中只需要保存下标);
  • 否则,只要 nums[i] 小于等于栈顶的元素值,就不断循环,撤销掉原先加入到 sum 中的值。循环结束后,从 nums[i]nums[j-1](假设现在的栈顶下标是 j) 的值都必须是 nums[i],把 nums[i] * (j - i) 加到 sum 中。

现在以数组 nums = [5, 3, 4, 1, 1] 为例,用图示来模拟上述计算 pre[i] 的过程。

(1)初始化单调栈 st,并放入哨兵 -1

(2)遍历数组 nums 开始计算,当前 i = 0:栈 s 的长度为 1 不满足大于 1 的要求,跳过 while 循环;计算当前和 sum = 0 + nums[i] * (i - st.top()) = 5 * (0 - (-1)) = 5;更新 pre[0] = 5,将 0 加入单调栈 st 中。

(3)i = 1:执行 while 循环,st 弹出 0,撤销 sum 中的 5sum = 5 - 5 = 0;当前和 sum = 0 + 3 * (1 - (-1)) = 6;更新 pre[1] = 6,将 1 加入单调栈 st 中。

(4)i = 2:不需要执行 while 循环;当前和 sum = 4 + 3 * (2 - 1) = 10;更新 pre[2] = 10,将 2 加入单调栈 st 中。

(5)i = 3:执行 while 循环,st 弹出 2,先撤销 sum 中的 4sum = 10 - 4 = 6,接着弹出 1 并撤销 sum 中的 23sum = 6 - 2 * 3 = 0;当前和 sum = 0 + 1 * (3 - (-1)) = 4;更新 pre[3] = 4,将 3 加入单调栈 st 中。

(6)i = 4:执行 while 循环,st 弹出 3,撤销 sum 中的 41sum = 4 - 1 * (3 - (-1)) = 0;当前和 sum = 0 + 1 * (4 - (-1)) = 5;更新 pre[4] = 5,将 1 加入单调栈 st 中。

(7)数组 pre 计算完成,pre[i] = [5, 6, 10, 4, 5]

数组 suf 的计算同理,这时候需要从右往左遍历。

实现代码

class Solution {
public:long long maximumSumOfHeights(vector<int>& nums) {int n = nums.size();vector<long long> pre(n), suf(n+1);stack<int> st;st.push(-1);    // 哨兵long long sum = 0;for (int i = 0; i < n; ++i) {int x = nums[i];while (st.size() > 1 && x <= nums[st.top()]) {int j = st.top();st.pop();sum -= (long long) nums[j] * (j - st.top());}sum += (long long) x * (i - st.top());pre[i] = sum;st.push(i);}st = stack<int>(); sum = 0;st.push(n); // 哨兵for (int i = n-1; i >= 0; --i) {int x = nums[i];while (st.size() > 1 && x <= nums[st.top()]) {int j = st.top();st.pop();sum -= (long long) nums[j] * (st.top() - j);}sum += (long long) x * (st.top() - i);suf[i] = sum;st.push(i);}long long res = 0;for (int i = 0; i < n; ++i) {res = max(res, pre[i] + suf[i+1]);}return res;}
};

复杂度分析

时间复杂度: O ( n ) O(n) O(n) n n n 为数组 nums 的长度。

空间复杂度: O ( n ) O(n) O(n),使用的额外空间为记录山峰左侧的最大和。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/298548.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

台达A2-M伺服

地址: P3.00 从站地址0x01~0x7F【1~127】 P3.01 通讯速度UZYX【0403】 X:0【4800】1【9600】2【19200】3【38400】4【57600】5【115200】Z:0【125Kbit/s】1【250】2【500】3【750】4【1Mbit/s】 P3.02 通讯格式6【8N2】7【8E1】8【8O1】 P3.03 1通讯错误刹停…

每日一题——LeetCode141.环形链表

个人主页&#xff1a;白日依山璟 专栏&#xff1a;Java|数据结构与算法|每日一题 文章目录 1. 题目描述示例1&#xff1a;示例2&#xff1a;示例3&#xff1a;提示: 2. 思路3. 代码 1. 题目描述 给你一个链表的头节点 head &#xff0c;判断链表中是否有环。 如果链表中有某…

synchronized详解

synchronized详解 基本使用源码解析常见面试题好书推荐 基本使用 Java中的synchronized关键字用于在多线程环境下确保数据同步。它可以用来修饰方法和代码块 当一个线程访问一个对象的synchronized方法或代码块时&#xff0c;其他线程将无法访问该对象的其他synchronized方法…

QT 构建项目报错Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7

问题 Getting NoClassDefFoundError: Could not initialize class org.codehaus.groovy.vmplugin.v7.Java7获取 NoClassDefFoundError&#xff1a;无法初始化类 org.codehaus.groovy.vmplugin.v7.Java7 解决方法一 java版本 过高 将java版本降低&#xff0c;例如从java17降…

「Verilog学习笔记」并串转换

专栏前言 本专栏的内容主要是记录本人学习Verilog过程中的一些知识点&#xff0c;刷题网站用的是牛客网 串并转换操作是非常灵活的操作&#xff0c;核心思想就是移位。串转并就是把1位的输入放到N位reg的最低位&#xff0c;然后N位reg左移一位&#xff0c;在把1位输入放到左移后…

「模问题」AI原生小游戏强势来袭!

WAVE SUMMIT 深度学习开发者大会2023 举办在即&#xff0c;为了让大家更好地体验文心大模型的各项能力&#xff0c;掌握Prompt的使用技巧&#xff0c;我们带来一个惊喜的消息&#xff1a;全新AI原生小游戏——「模问题」火热上线啦&#xff01; 「模问题」是基于文心大模型的能…

磁钢的取向和充磁方向

充磁是磁钢生产中的必备工序&#xff0c;如果磁铁不充磁&#xff0c;就不具备磁性&#xff0c;也就丧失了作为永磁材料的基本功能。磁钢作为一个立体的工件&#xff0c;形状和尺寸各异&#xff0c;如何给磁钢充磁&#xff1f;不同方向的充磁效果一样吗&#xff1f;今天我们就来…

智能仓储管理系统设计与实现

智能仓储管理系统设计与实现 第一章 绪论 1.1 设计背景 物联网&#xff08;英文&#xff1a;Internet of Things&#xff0c;缩写&#xff1a;IoT&#xff09;是万物相连的互联网&#xff0c;即把所有物品通过信息传感设备与互联网连接起来&#xff0c;以实现智能化识别、定位、…

C++ 比 C语言增加的新特性 3 之 命名空间namespace

1. 命名空间 1.1 命名空间 又称为“名字空间”&#xff0c;在内存&#xff08;全局&#xff09;中取一块区域并对其进行命名 实际例子&#xff1a; 同一个班级&#xff0c;两个同姓的人&#xff0c;例如&#xff1a;张三和张三&#xff0c;其中一个张三座位是在讲台右边&am…

Tg5032skn:高稳定性105℃高温

TG5032SKN是一款频率范围10MHz ~ 54MHz,具有高稳定的TCXO晶振&#xff0c;可与CMOS或裁剪正弦输出。外部尺寸5.0 3.2 1.45mm&#xff0c;超小型,质地轻。该系列晶振的额定工作范围-40℃~&#xfe62;105C内可高稳定性工作&#xff0c;使得信号频率的误差很小。。TG5032SKN与其…

电赛论文模板

2023全国大学生电子设计大赛 &#xff08;E 题&#xff09; 【本科组】 2023年8月5日 运动目标控制与自动追踪系统 摘 要 本设计以基于意法半导体与ARM公司生产的STM32F103RCT6单片机为控制核心&#xff0c;配合LM2596S降压模块&#xff0c;OPENMV&#xff0c;OLED显示屏&…