給定乙個大小為n≤106
的陣列。
有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。
您只能在視窗中看到k
個數字。
每次滑動視窗向右移動乙個位置。
以下是乙個例子:
該陣列為[1 3 -1 -3 5 3 6 7]
,k
為3
。
視窗位置
最小值最大值
[1 3 -1] -3 5 3 6 7-13
1 [3 -1 -3] 5 3 6 7-33
1 3 [-1 -3 5] 3 6 7-35
1 3 -1 [-3 5 3] 6 7-35
1 3 -1 -3 [5 3 6] 736
1 3 -1 -3 5 [3 6 7]37
您的任務是確定滑動視窗位於每個位置時,視窗中的最大值和最小值。
輸入格式
輸入包含兩行。
第一行包含兩個整數n
和k
,分別代表陣列長度和滑動視窗的長度。
第二行有n
個整數,代表陣列的具體數值。
同行資料之間用空格隔開。
輸出格式
輸出包含兩個。
第一行輸出,從左至右,每個位置滑動視窗中的最小值。
第二行輸出,從左至右,每個位置滑動視窗中的最大值。
輸入樣例:
8 3
1 3 -1 -3 5 3 6 7
輸出樣例:-1 -3 -3 -3 3 3
3 3 5 5 6 7
通過讀題,我們可以簡單描述為有乙個長度為n
的陣列a[n]
,給定乙個長度為k
的「視窗」,a[n]
會從頭開始依次經過這個視窗,我們需要求的是陣列從第k - 1
個元素開始,也就是視窗第一次被填滿時開始一直到陣列結尾,每一次視窗中的值被更新後的最大值和最小值
不難發現,這個視窗是乙個從尾部進入,頭部出去的模型,那很容易聯想到先入先出的資料結構——佇列,我們可以假設這個視窗就是乙個佇列,每次陣列元素會從隊尾入隊,當視窗被填滿後,當前的隊頭元素要出隊,我們維護這樣乙個長度為k
的佇列,每次求出它的最大值和最小值即可
然後即便我們想到使用佇列進行求解,這個問題還是顯得十分複雜,我們怎樣簡化它呢?答案就是使用單調佇列
單調佇列即佇列中的元素滿足單調遞增或遞減的性質,保證隊頭隊尾元素是佇列的最大值或最小值,因為從模擬這道題的過程我們可以得出,假設在求視窗中的最小值時,陣列存在[..., 3, -1, 0, ...]
這樣一段序列,當3
入隊時,它可能是當前隊中最小的元素,但當視窗再一次向後移動時,-1
進入佇列,此時無論如何3
都不會再被當成最小值輸出,因為-1
一定會在3
之後出隊,所以這時3
就沒有必要再存在於隊中,我們將它排除,如此迴圈,使得每次入隊的元素一定大於前面的元素,我們就可以得到乙個單調遞增的佇列,此時求最小值,我們直需要返回隊頭元素即可
以上是最小值,求最大值時我們只需要改變元素入隊時的判斷條件,即可改變單調佇列的單調性,使隊頭元素變成最大值,下面是**
#include
using namespace std;
const
int n =
1000010
;int q[n]
, a[n]
;int n, k;
intmain()
puts(""
);hh =
0, tt =-1
;// 最大值
for(
int i =
0; i < n;
++i)
}
這裡我們使用q[n]
來表示滑動視窗中陣列元素的下標,這樣更方便我們對佇列進行操作 單調佇列 滑動視窗
nkoj 2152 description 給你乙個長度為n n 10 6 的陣列,乙個長為k的滑動的窗體從最左移至最右端,你只能見到視窗的k個數,每次窗體向右移動一位,找出窗體所包含的數字的最大和最小值,如下表所示 k的值為3 視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 ...
滑動視窗 單調佇列
給定乙個大小為n 106的陣列。有乙個大小為k的滑動視窗,它從陣列的最左邊移動到最右邊。您只能在視窗中看到k個數字。每次滑動視窗向右移動乙個位置。以下是乙個例子 該陣列為 1 3 1 3 5 3 6 7 k為3。視窗位置 最小值 最大值 1 3 1 3 5 3 6 7 1 3 1 3 1 3 5 3...
單調佇列 滑動視窗
p1886 滑動視窗 模板 單調佇列 有乙個長為 n 的序列 a,以及乙個大小為 k 的視窗。現在這個從左邊開始向右滑動,每次滑動乙個單位,求出每次滑動後視窗中的最大值和最小值。如果按照暴力方法做的話,每一次判斷相鄰的k個數的最大值和最小值,複雜度為o n k 肯定會超時,因此就想到把每次的最大值和...