給你乙個滑動視窗和乙個陣列,滑動視窗從陣列第乙個元素開始向後滑動,每滑動一下就計算當前視窗中對應的陣列元素的最大值;
設定視窗長度為m,陣列長度為n,有o(n*m)演算法,用最大堆的o(n*lgm)算,利用已經比較過的元素之間關係的o(n)演算法;
摘自部落格
給定乙個陣列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)。**如下:
/*最大滑動視窗主函式*/
void
maxslidingwindow(
inta,
intn,
intw,
intb)
/*求陣列最大值*/
intmax(
inta,
intn)
} return
max;
}
第1個方法思路簡單,但是時間複雜度過高,因此需要改進。可以使用乙個最大堆來儲存w個數字,每次插入數字時只需要o(lgw)的時間,從堆中取最大值只需要o(1)的時間。隨著視窗由左向右滑動,因此堆中有些數字會失效(因為它們不再包含在視窗中)。
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)。
void
maxslidingwindow(
inta,
intn,
intw,
intb)
for(int
i = w; i < n; i++)
b[n-w] = a[q.front()];
}
滑動視窗最大值
題目描述 給定乙個陣列和滑動視窗的大小,找出所有滑動視窗裡數值的最大值。例如,如果輸入陣列及滑動視窗的大小3,那麼一共存在6個滑動視窗,他們的最大值分別為 針對陣列的滑動視窗有以下6個 幾個注意點 利用雙端佇列實現,如果後者比前者大,前者丟擲,後者進,如果比前者小,壓入佇列,判斷隊頭是否過期,這就需...
滑動視窗最大值
給定乙個陣列和滑動視窗的大小,請找出所有滑動視窗裡的最大值。public class 滑動視窗的最大值 if num.length size size 1 用來儲存可能是滑動視窗最大值的數字的下標 linkedlist indexdeque newlinkedlist for int i 0 i s...
滑動視窗最大值
給定乙個陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗內的 k 個數字。滑動視窗每次只向右移動一位。返回滑動視窗中的最大值。示例 輸入 nums 1,3,1,3,5,3,6,7 和 k 3 輸出 3,3,5,5,6,7 解釋 滑動視窗的位置 最大...