单调栈-907. 子数组的最小值之和
2022-05-25 21:40:29
问题描述:
给定一个整数数组 arr,找到 min(b) 的总和,其中 b 的范围为 arr 的每个(连续)子数组。
由于答案可能很大,因此 返回答案模 10^9 + 7 。
示例 1:
输入:arr = [3,1,2,4]
输出:17
解释:
子数组为 [3],[1],[2],[4],[3,1],[1,2],[2,4],[3,1,2],[1,2,4],[3,1,2,4]。
最小值为 3,1,2,4,1,1,2,1,1,1,和为 17。
示例 2:
输入:arr = [11,81,94,43,3]
输出:444
提示:
1 <= arr.length <= 3 * 104
1 <= arr[i] <= 3 * 104
问题求解:
本题需要考虑每个元素的管辖范围:对应nums[i]以其为最小值的范围[l, r]。
这一步可以通过单调栈求得。
但有一点需要特别注意:去重。
这里的去重逻辑是采用单边逻辑,例如取左边第一个小于nums[i]的位置,取右边第一个小于等于nums[i]的位置。
class Solution:
def sumSubarrayMins(self, arr: List[int]) -> int:
n = len(arr)
left = [0] * n
right = [0] * n
stk = []
for i in range(n - 1, -1, -1):
while stk and arr[stk[-1]] > arr[i]:
stk.pop()
right[i] = stk[-1] - i if stk else n - i
stk.append(i)
stk = []
for i in range(n):
while stk and arr[stk[-1]] >= arr[i]:
stk.pop()
left[i] = i - stk[-1] if stk else i + 1
stk.append(i)
res = 0
mod = int(1e9 + 7)
for i in range(n):
res = (res + arr[i] * left[i] * right[i]) % mod
return res

浙公网安备 33010602011771号