美丽塔 II (LeetCode日记)
LeetCode-2866-美丽塔 II
题目信息:
给你一个长度为 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 <= heights[i] <= maxHeights[i] 1<=heights[i]<=maxHeights[i]
- heights 是一个 山脉 数组。
如果存在下标 i i i 满足以下条件,那么我们称数组 h e i g h t s heights heights 是一个 山脉 数组:
- 对于所有 0 < j < = i 0 < j <= i 0<j<=i ,都有 h e i g h t s [ j ? 1 ] < = h e i g h t s [ j ] heights[j - 1] <= heights[j] heights[j?1]<=heights[j]
- 对于所有 i < = k < n ? 1 i <= k < n - 1 i<=k<n?1 ,都有 h e i g h t s [ k + 1 ] < = h e i g h t s [ k ] heights[k + 1] <= heights[k] heights[k+1]<=heights[k]
请你返回满足 美丽塔 要求的方案中,高度和的最大值
- 示例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]
输出:13
解释:和最大的美丽塔方案为 h e i g h t s = [ 5 , 3 , 3 , 1 , 1 ] heights = [5,3,3,1,1] heights=[5,3,3,1,1] ,这是一个美丽塔方案
因为:
- 1 < = h e i g h t s [ i ] < = m a x H e i g h t s [ i ] 1 <=heights[i] <= maxHeights[i] 1<=heights[i]<=maxHeights[i]
- h e i g h t s heights heights 是个山脉数组,峰值在 i = 0 i = 0 i=0 处 。
则有:13是所有美丽塔方案中的最大高度和。
- 示例2:
输入: m a x H e i g h t s = [ 6 , 5 , 3 , 9 , 2 , 7 ] maxHeights = [6,5,3,9,2,7] maxHeights=[6,5,3,9,2,7]
输出:22
解释: 和最大的美丽塔方案为 h e i g h t s = [ 3 , 3 , 3 , 9 , 2 , 2 ] heights =[3,3,3,9,2,2] heights=[3,3,3,9,2,2] ,这是一个美丽塔方案
因为:
- 1 < = h e i g h t s [ i ] < = m a x H e i g h t s [ i ] 1 <= heights[i] <= maxHeights[i] 1<=heights[i]<=maxHeights[i]
- h e i g h t s heights heights 是个山脉数组,峰值在 i = 3 i = 3 i=3 处。
则有:22 是所有美丽塔方案中的最大高度和。
- 示例3:
输入:$maxHeights = [3,2,5,5,2,3] $
输出:18
解释:和最大的美丽塔方案为 h e i g h t s = [ 2 , 2 , 5 , 5 , 2 , 2 ] heights =[2,2,5,5,2,2] heights=[2,2,5,5,2,2] ,这是一个美丽塔方案
因为:
- 1 < = h e i g h t s [ i ] < = m a x H e i g h t s [ i ] 1 <= heights[i] <= maxHeights[i] 1<=heights[i]<=maxHeights[i]
- h e i g h t s heights heights 是个山脉数组,最大值在 i = 2 i = 2 i=2 处。
注意,在这个方案中,i = 3 也是一个峰值。
18 是所有美丽塔方案中的最大高度和。
提示:
- 1 < = n = = m a x H e i g h t s < = 105 1 <= n == maxHeights <= 105 1<=n==maxHeights<=105
- 1 < = m a x H e i g h t s [ i ] < = 109 1 <= maxHeights[i] <= 109 1<=maxHeights[i]<=109
题目类型: 栈、数组、单调栈
题解
Leetcode定级为中等难度,标准的做法,对我来说却难的飞起。做题做的太少咯。
下面我们看题目解析。
根据题意可以知道,假设数组的长度为
n
n
n,对于山状数组
h
e
i
g
h
t
s
heights
heights
定义如下:
- 假设
h
e
i
g
h
t
s
[
i
]
heights[i]
heights[i]为数组中的最大值,则
i
i
i 左边的值均小于等于
h
e
i
g
h
t
s
[
i
]
heights[i]
heights[i],
i
i
i 右边的值均小于等于
h e i g h t s [ i ] heights[i] heights[i]; - i i i 的左侧,从 0 0 0 开始到 i i i 为非递减关系,即 j ∈ [ 1 , i ] j∈[1,i] j∈[1,i] 时,均满足 h e i g h t s [ j ? 1 ] ≤ h e i g h t s [ j ] heights[j?1]≤heights[j] heights[j?1]≤heights[j];
- i i i 的右侧,从 i i i 开始到 n ? 1 n?1 n?1 为非递增关系,即 j ∈ [ i , n ? 2 ] j∈[i,n?2] j∈[i,n?2] 时,均满足 h e i g h t s [ j + 1 ] ≤ h e i g h t s [ j ] heights[j+1]≤heights[j] heights[j+1]≤heights[j];
题目给定了山状数组数组中每个元素的上限,即 h e i g h t s [ i ] ≤ m a x H e i g h t s [ i ] heights[i]≤maxHeights[i] heights[i]≤maxHeights[i],题目要求返回的山状数组所有元素之和的最大值。根据以上分析可知:
- 对于 j ∈ [ 0 , i ? 1 ] j∈[0,i?1] j∈[0,i?1] 时,此时 m a x ? ( h e i g h t s [ j ] ) = m i n ? ( h e i g h t s [ j + 1 ] , m a x H e i g h t s [ j ] ) max?(heights[j])=min?(heights[j+1],maxHeights[j]) max?(heights[j])=min?(heights[j+1],maxHeights[j])
- 对于 j ∈ [ i + 1 , n ? 1 ] j∈[i+1,n?1] j∈[i+1,n?1]时,此时 m a x ? ( h e i g h t s [ j ] ) = m i n ? ( h e i g h t s [ j ? 1 ] , m a x H e i g h t s [ j ] ) max?(heights[j])=min?(heights[j?1],maxHeights[j]) max?(heights[j])=min?(heights[j?1],maxHeights[j])
- 假设此时山状数组的山顶为 h e i g h t s [ i ] heights[i] heights[i],此时整个山状数组的所有元素的最大值即可确定,此时数组元素和的最大值也可确定
- 对于数组中的每个元素尽量取最大值使得整个数组元素之和最大
暴力法:
根据以上分析,我们依次枚举以
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
[
i
]
maxHeights[i]
maxHeights[i]为山顶,在内层循环中分别求出
i
i
i 的左侧元素与右侧的元素,即可求出所有元素之和,此时需要的时间复杂度为
O
(
n
2
)
O(n^2)
O(n2)。
请看我的暴力代码:(773 / 785 个通过的测试用例,会超时!!!)
class Solution(object):
def maximumSumOfHeights(self, maxHeights):
"""
:type maxHeights: List[int]
:rtype: int
"""
lens = len(maxHeights)
heights = [0] * lens
maxiume = 0
for i in range(lens):
n = i - 1
heights[i] = maxHeights[i]
while n >= 0: # 先处理左边递增
heights[n] = min(heights[n + 1], maxHeights[n])
n = n-1
n = i + 1
while n < lens: # 再处理右边递减
heights[n] = min(heights[n - 1], maxHeights[n])
n = n + 1
maxiume = max(sum(heights), maxiume)
heights = [0] * lens
return maxiume
按照题目给定的数量级会存在超时,需要进一步优化。
我只会简单的方法了,现在向大家介绍一下大佬们的想法思路。
动态规划 + 单调栈:
我们定义
f
[
i
]
f[i]
f[i] 表示前
i
+
1
i+1
i+1 座塔中,以最后一座塔作为最高塔的美丽塔方案的高度和。我们可以得到如下的状态转移方程:
f
[
i
]
=
{
f
[
i
?
1
]
+
?heights?
[
i
]
,
?if?heights?
[
i
]
≥
?heights?
[
i
?
1
]
?heights?
[
i
]
×
(
i
?
j
)
+
f
[
j
]
,
?if?heights?
[
i
]
<
?heights?
[
i
?
1
]
f[i]=\left\{\begin{array}{ll}f[i-1]+\text { heights }[i], & \text { if heights }[i] \geq \text { heights }[i-1] \\\text { heights }[i] \times(i-j)+f[j], & \text { if heights }[i]<\text { heights }[i-1]\end{array}\right.
f[i]={f[i?1]+?heights?[i],?heights?[i]×(i?j)+f[j],??if?heights?[i]≥?heights?[i?1]?if?heights?[i]<?heights?[i?1]?
其中
j
j
j 是最后一座塔左边第一个高度小于等于
h
e
i
g
h
t
s
[
i
]
heights[i]
heights[i]的塔的下标。我们可以使用单调栈来维护这个下标。至于什么是单调栈,不懂得小伙伴可以去其他博客上学习学习,我在这里就不一一赘述了。
我们可以使用类似的方法求出
g
[
i
]
g[i]
g[i],表示从右往左,以第 iii 座塔作为最高塔的美丽塔方案的高度和。最终答案即为
f
[
i
]
+
g
[
i
]
?
h
e
i
g
h
t
s
[
i
]
f[i]+g[i]?heights[i]
f[i]+g[i]?heights[i] 的最大值。
Ok,下面请看代码:
class Solution:
def maximumSumOfHeights(self, maxHeights: List[int]) -> int:
n = len(maxHeights)
stk = []
left = [-1] * n
for i, x in enumerate(maxHeights):
while stk and maxHeights[stk[-1]] > x:
stk.pop()
if stk:
left[i] = stk[-1]
stk.append(i)
stk = []
right = [n] * n
for i in range(n - 1, -1, -1):
x = maxHeights[i]
while stk and maxHeights[stk[-1]] >= x:
stk.pop()
if stk:
right[i] = stk[-1]
stk.append(i)
f = [0] * n
for i, x in enumerate(maxHeights):
if i and x >= maxHeights[i - 1]:
f[i] = f[i - 1] + x
else:
j = left[i]
f[i] = x * (i - j) + (f[j] if j != -1 else 0)
g = [0] * n
for i in range(n - 1, -1, -1):
if i < n - 1 and maxHeights[i] >= maxHeights[i + 1]:
g[i] = g[i + 1] + maxHeights[i]
else:
j = right[i]
g[i] = maxHeights[i] * (j - i) + (g[j] if j != n else 0)
return max(a + b - c for a, b, c in zip(f, g, maxHeights))
- 研究生在读,我会尽量保持LeetCode每日一题的思路和代码输出。希望大家多多支持。
- 水平有限,希望各位大佬能够批评指正。您的教诲是我进步的船帆。
- 希望各位跟我一样的小白能跟我一起参与到做题和讨论中来。共同进步是我所能期盼的最高愿想。
- 您的点赞和关注是我坚持分享的动力泉源,希望能将这件简单平凡的事一直做下去。感谢大家。
本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。 如若内容造成侵权/违法违规/事实不符,请联系我的编程经验分享网邮箱:veading@qq.com进行投诉反馈,一经查实,立即删除!