📅  最后修改于: 2023-12-03 15:25:55.872000             🧑  作者: Mango
给定一个由非负整数构成的长度为 n
的数组 nums
,代表一个由 nums[0]
到 nums[n - 1]
升序排列的数组。
请你返回每个 子数组 的最小元素的 总和。
其中,子数组定义为原数组中的一个连续的下标序列。
请注意,大小为 k
的子数组共有 n - k + 1
个,其中 k
是子数组的大小。
例如,[1,2,3]
、[2,3]
、[1,2]
都是不同的子数组。
对于每个子数组,我们需要找到其中的最小值并加到总和中。对于长度为 k
的子数组,最小值的位置一定是在该子数组中,在该子数组的所有元素中遍历一遍即可。因此,我们可以使用两层循环遍历所有子数组和子数组中的元素,时间复杂度为 $O(n^2)$。
但是,我们可以利用单调栈来优化此算法。具体地,我们维护一个单调递增栈 stack
,遍历原数组 nums
时,如果当前元素 num
大于栈顶元素,则直接将其入栈;否则,我们将栈顶元素弹出,并加上弹出元素在原数组中左边、右边第一个小于其的元素的位置之积,加到总和中。我们可以证明,这样的操作可以保证在每个子数组中都找到了最小值。
据此,我们可以使用单调栈在 $O(n)$ 时间内遍历原数组,得到所有子数组的最小值的总和。
以下是 Python 代码实现:
class Solution:
def sumSubarrayMins(self, nums: List[int]) -> int:
"""
:type nums: List[int]
:rtype: int
"""
stack = []
res = 0
nums = [0] + nums + [0]
for i, num in enumerate(nums):
while stack and nums[stack[-1]] > num:
j = stack.pop()
k = stack[-1]
res += nums[j] * (i - j) * (j - k)
stack.append(i)
return res % (10**9 + 7)
本问题通过单调栈的优化,提高了算法的时间复杂度。同时,本问题也展示了单调栈在解决相关问题中的威力。