最大滑動視窗

2021-07-29 07:42:11 字數 2023 閱讀 5078

給定乙個陣列a,有乙個大小為w的滑動視窗,該滑動視窗從最左邊滑到最後邊。在該視窗中你只能看到w個數字,每次只能移動乙個位置。我們的目的是找到每個視窗w個數字中的最大值,並將這些最大值儲存在陣列b中。

例如陣列a=[1 3 -1 -3 5 3 6 7], 視窗大小w為3。則視窗滑動過程如下所示:

window position                max

--------------- -----

[1 3 -1] -3 5 3 6 7 3

1 [3 -1 -3] 5 3 6 7 3

1 3 [-1 -3 5] 3 6 7 5

1 3 -1 [-3 5 3] 6 7 5

1 3 -1 -3 [5 3 6] 7 6

1 3 -1 -3 5 [3 6 7] 7

輸入引數為陣列a和w大小

輸出為陣列b,其中b[i]儲存了a[i]到a[i+w-1]中w個數字的最大值。

乙個最簡單的想法就是每次移動都計算w個數字的最大值並儲存起來,每次計算w個數字的最大值需要o(w)的時間,而滑動過程需要滑動n-w+1次,n為陣列大小,因此總共的時間為o(nw)。**如下:

[cpp]view plain

copy

/*最大滑動視窗主函式*/

void

maxslidingwindow(

inta, 

intn, 

intw, 

intb)   

/*求陣列最大值*/

intmax(

inta, 

intn)  

}  return

max;  

}  

第1個方法思路簡單,但是時間複雜度過高,因此需要改進。可以使用乙個最大堆來儲存w個數字,每次插入數字時只需要o(lgw)的時間,從堆中取最大值只需要o(1)的時間。隨著視窗由左向右滑動,因此堆中有些數字會失效(因為它們不再包含在視窗中)。

[cpp]view plain

copy

typedef

pair<

int, 

int> pair;  

void

maxslidingwindow(

inta, 

intn, 

intw, 

intb)  

q.push(pair(a[i], i));  

}  b[n-w] = q.top().first;  

}  

如果陣列本身有序,則裡面的while迴圈不會執行,堆大小會增大到n。

因為堆大小並不保持在w不變

,因此該演算法時間複雜度為o(nlgn)。

最大堆解法在堆中儲存有冗餘的元素,比如原來堆中元素為[10 5 3],新的元素為11,則此時堆中會儲存有[11 5 3]。其實此時我們可以清空整個佇列,然後再將11加入到佇列即可,即只在佇列中保持[11]。使用雙向佇列可以滿足要求,滑動視窗的最大值總是儲存在佇列首部佇列裡面的資料總是從大到小排列。當遇到比當前滑動視窗最大值更大的值時,則將佇列清空,並將新的最大值插入到佇列中。如果遇到的值比當前最大值小,則直接插入到佇列尾部。每次移動的時候需要判斷當前的最大值是否在有效範圍,如果不在,則需要將其從佇列中刪除。由於每個元素最多進隊和出隊各一次,因此該演算法時間複雜度為o(n)。

[cpp]view plain

copy

void

maxslidingwindow(

inta, 

intn, 

intw, 

intb)   

for(int

i = w; i 

b[n-w] = a[q.front()];  

}  

最大滑動視窗

題目描述 給定乙個陣列a,有乙個大小為w的滑動視窗,該滑動視窗從最左邊滑到最後邊。在該視窗中你只能看到w個數字,每次只能移動乙個位置。我們的目的是找到每個視窗w個數字中的最大值,並將這些最大值儲存在陣列b中。例如陣列a 1 3 1 3 5 3 6 7 視窗大小w為3。則視窗滑動過程如下所示 wind...

最大滑動視窗

給定乙個陣列a,有乙個大小為w的滑動視窗,該滑動視窗從最左邊滑到最後邊。在該視窗中你只能看到w個數字,每次只能移動乙個位置。我們的目的是找到每個視窗w個數字中的最大值,並將這些最大值儲存在陣列b中。例如陣列a 1 3 1 3 5 3 6 7 視窗大小w為3。則視窗滑動過程如下所示 window po...

239 最大滑動視窗

滑動視窗當中的最大值 掃瞄正個陣列,o n 每個節點處需要進行掃瞄k個節點,所有時間複雜度為o nk class solution return result private void helper int nums,int start,int end,int result,int i result...