962. 最大宽度坡
给定一个整数数组
A
,坡是元组 (i, j)
,其中 i < j
且 A[i] <= A[j]
。这样的坡的宽度为 j - i
。找出
A
中的坡的最大宽度,如果不存在,返回 0 。示例 1:
输入:[6,0,8,2,1,5] 输出:4 解释: 最大宽度的坡为 (i, j) = (1, 5): A[1] = 0 且 A[5] = 5.
示例 2:
输入:[9,8,1,0,1,9,4,0,4,1] 输出:7 解释: 最大宽度的坡为 (i, j) = (2, 9): A[2] = 1 且 A[9] = 1.
提示:
2 <= A.length <= 50000
0 <= A[i] <= 50000
通过次数15,673提交次数34,873
法1 单调栈
思路
首先正序遍历数组
A
,将以 A[0]
开始的递减序列的元素下标依次存入栈中。为什么要存从A[0]
开始的递减序列呢? 因为题中条件A[i] <= A[j]
,所以要让A[i]
的值尽可能的小,即从A[0]
开始的一个递减序列。单调栈中记录的是从后往前每个大分段 “坡底” 所在的位置。
以
[6, 1, 8, 2, 0, 5]
为例,由于 (6, 1, 0)
是递减的,所以栈中存的元素应该为:(栈顶 -> (4, 1, 0)
<- 栈底)。其中[2, 0, 5]
也是一个满足条件的坡并且宽度为2
,但是为什么在计算的时候没有算它呢? 因为该数组从A[0]
开始的递减序列为(6, 1, 0)
并没有元素2
,是因为在元素2
的左边有比它还要小的元素1
。当计算最大宽度坡时1
和2
相比,不管是元素值还是元素的下标都更小,所以若以2
为坡底能计算出某一坡的宽度时同样的以1
为坡底也能计算出相应的坡的宽度并且宽度更大,所以就不需要计算以2
为坡底的坡的宽度了。
此时栈 stack:
(4(0), 1(1), 0(6))
:然后逆序遍历数组 A
,若以栈顶元素为下标的元素值 A[stack.peek()]
小于等于当前遍历的元素 A[i]
,即 A[stack.peek()] <= A[i]
。此时就是一个满足条件的坡的宽度,并且这个宽度一定是栈顶这个坡底 i
能形成的最大宽度,将栈顶元素出栈并计算当前坡的宽度,保留最大值即可。为什么找到一个右端点j
之后,可以不断的将满足条件的栈顶元素弹出来呢? 因为我们的j
是是从右向左遍历的,此时的宽度已经是i能匹配到的最大宽度了!也就是说,i
的价值已经发挥了最大了。
题解
class Solution: def maxWidthRamp(self, nums: List[int]) -> int: if len(nums) <= 1: return len(num) # 保存 递减元素的下标 stack = [] for i in range(0, len(nums)): while len(stack) == 0 or nums[i] < nums[stack[-1]]: stack.append(i) res = 0 for i in range(len(nums)-1, -1, -1): while stack and nums[i] >= nums[stack[-1]]: res = max(res, i - stack[-1]) stack.pop() return res