經典題目 子陣列的最小值之和 單調棧

2021-10-07 20:17:27 字數 1685 閱讀 2538

思路是單調棧

比如輸入[1,3,2],初始dot = 0, ans = 0。

首先,1入棧,dot += 1 * 1,這個加上的1對應區間為[1],ans += dot, ans = 1

然後,3入棧,dot += 3 * 1,即dot = 4 = 1 + 3,這裡的1對應的區間為[1, 3], 3對應的區間為[3],ans += dot,ans = 1 + (1 + 3),對應的區間為[1], [1,3], [3]

最後,2入棧前將3彈出棧,彈出的時候dot -= 3 * 1, dot = 1,這個剩下的1對應區間是[1,3],被減去的3代表區間[3],因為[3,2]的最小值將變為2,而不是3。2入棧時,count = 2,即兩個區間[3,2],[2]的最小值都是2。dot += 2 * 2,dot = 1 + 2 + 2,對應的區間為[1,3,2], [3,2], [2],ans += dot, ans = 1 + (1 + 3) + (((1 + 3) - 3) + 2 + 2) = 1 + (1 + 3) + (1 + 2 + 2)。對應區間為[1], [1,3], [3],[1,3,2],[3,2],[2]

換句話說,count始終維護了,以當前index的數值a[index]為最小值的區間個數,dot維護了以a[:index]中為最小值的區間的和。

class

solution

:def

sumsubarraymins

(self, a: list[

int])-

>

int:

mod =

10**9+

7 stack =

# 迴圈中表示含有當前數字的數字的,最小值之和。未必當前數字是最小值

doc =

0 res =

0for i in

range

(len

(a))

: count =

1while stack and stack[-1

][0]

>=a[i]

: cur, num = stack.pop(

)# 新的值取代了老的值,以老的值作為最小值的陣列都給了當前值。

count += num

# 減去相關的陣列的最小值的和 num陣列的數量 cur 彈出的數字

doc -= num*cur

# 是乙個單調上公升的棧,前面的都會被彈出

(a[i]

, count)

)# 第一項是數值,第二項是以該數值為最小值的區間個數

# 新增上以當前數字作為最小值的數量

doc += count*a[i]

# 加上含有當前數字,但是未必是最小值的陣列的,最小值和

res += doc

res %= mod

return res

LeetCode 子陣列的最小值之和

一開始的思路是打算先求出所有子陣列,然後排序子陣列,最後相加,然而運算太複雜,會超出時間限制 sumsubarraymins arr for let k 0 k allarr.length k res allarr k 0 console.log allarr console.log res 後來改...

907 子陣列的最小值之和

碰到leetcode907,子陣列的最小值之和,用python3按自己思路寫死都過不去,怎麼都超時,這是python3 class solution def sumsubarraymins self,a type a list int rtype int res 0 length len a for...

907 子陣列的最小值之和

題目描述 給定乙個整數陣列 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...