1. 程式人生 > 其它 >單調棧-907. 子陣列的最小值之和

單調棧-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