給定乙個陣列,固定數 num,該陣列的子陣列中,有多少個子陣列滿足 在該子陣列中最大值 - 最小值 小於或者等於 num?
但這裡額外需要了解兩個性質,
證明: 假設視窗左邊界為 left , 右邊界為 right,如果滿足題目條件,則 max - min <= num,也就是說,在該視窗內,任意乙個數都不會對於 max,任意乙個數都不會小於 min ,所以該視窗內的子陣列必然 sub_max 小於等於 max , sub_min 大於等於 min,因此 sub_max - sub_min 也必然滿足條件;
證明:不滿足條件,說明 max - min > num,那麼視窗向右擴的時候,考慮極端情況,進來的數比 max 大, 此時結果更不可能滿足,而進來的數比 min 數小時,還是不可能滿足,至於進來的數在兩者中間,那對結果根本就不會產生任何影響;(這裡,視窗的左邊界始終保持不動,只有右邊界在動)
解題思路:乙個陣列中的子陣列,可以看成是以當前位置為左邊界,右邊界不斷向右擴張,那麼從頭開始以 0 位置作為左邊界,以左邊界為起始位置,右邊界不斷遍歷剩餘陣列,就得到了所有的子陣列。
同樣借助雙端佇列,乙個儲存當前視窗(也就是子陣列)內的最大值,另乙個儲存最小值,佇列的更新邏輯不變,left 假設為左邊界, right為右邊界,left 從 0 開始,而 right 以上一次擴失敗(不滿足條件就表示擴失敗,滿足條件就繼續往右)的地方再繼續往右擴(第一次就以0為起始位置);
至於為什麼下一次要以上次擴失敗的地方開始,就涉及到了性質2,因為上次擴失敗就意味著不滿足條件,那麼由性質2得知只要它的左邊界不動,那麼再往右擴也不會滿足條件的,所以此時應該停止往右;要想繼續往右走,就需要進入下一次的迴圈左邊界往右動。
當右邊界停止擴的時候,如何獲取當前視窗內滿足條件的子陣列,就用到了性質1。當前右邊界停止往右的原因是當前 right 不滿足條件,那後退一步的時候它就是滿足條件了,也就是說 left ~ right - 1的視窗內是滿足條件的,由性質1就可以得出當前視窗的所有子陣列都一定滿足條件。而以 left ~ right - 1為邊界內的子陣列數應該是 (right - 1) - left + 1 = right - left。
準備兩個佇列,分別存放視窗最小值、最大值,左右邊界 left = 0, right = 0,初始化res = 0;
外迴圈left 從0 開始,內部right 迴圈也從0 開始,更新佇列;
更新之後,根據佇列頭部值判斷是否滿足條件,是 right 繼續往右擴,即 +1, 否 直接break,中斷內部 right 迴圈,left = 1 視窗左邊界往右移動一次,此時right 接著上個結束迴圈的位置繼續判斷;
判斷佇列中頭部值是否過期;
更新子陣列數。
from collections import deque
defgetnum
(arr, num)
: deque_min = deque(
) deque_max = deque(
) left, right =0,
0 res =
0while
(left <
len(arr)):
while
(right <
len(arr)):
# 更新佇列
while
(len
(deque_min)!=0
and deque_min[-1
]>= arr[right]):
deque_min.pop(
)while
(len
(deque_max)!=0
and deque_max[-1
]<= arr[right]):
deque_max.pop(
)if deque_max[0]
- deque_min[0]
> num:
# 不滿足條件,右邊界再繼續擴也沒有意義,中斷 while 迴圈
break
right +=
1# 滿足條件的話,右邊界繼續擴
# 判斷佇列中值是否過期
if deque_min[0]
== left:
deque_min.popleft(
)if deque_max[0]
== left:
deque_max.popleft(
)# 滿足條件的子陣列數量
res = res + right - left #
# left +=
1return res
最大值減去最小值小於或等於num的子陣列數量
給定陣列arr和整數num,共返回有多少個子陣列滿足如下情況 max arr i j min arr i j num mar arr i j 表示陣列arr i j 中的最大值,min arr i j 表示子陣列arr i j 中的最小值。如果陣列長度為n,請事先時間複雜度為 o n 的解法。具體思...
最大值減去最小值小於或等於num的子陣列的數量
給定陣列arr和整數num,返回共有多少個子陣列滿足如下情況 max arr i.j min arr i.j num 要求 o n 實現。思路 使用兩個有序佇列 相對於有序棧來命名 qmax和qmin,分別維護arr i.j 的最大值和最小值更新結構。當子陣列a i.j 向右滑動乙個位置變成arr ...
最大值減去最小值小於或等於num的子陣列數量
給定陣列 arr 和整數 num,共返回有多少個子陣列滿足如下情況 max arr i j min arr i j num max arr i j 表示子陣列arr i j 中的最大值,min arr i j 表示子陣列arr i j 中的最小值。輸入描述 第一行輸入兩個數 n 和 num,其中 n...