239. 滑動視窗最大值
給你乙個整數陣列nums
,有乙個大小為k
的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗內的k
個數字。滑動視窗每次只向右移動一位。
返回滑動視窗中的最大值。
示例 1:
輸入:nums = [1,3,-1,-3,5,3,6,7], k = 3
輸出:[3,3,5,5,6,7]
解釋:滑動視窗的位置 最大值
--------------- -----
[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
示例 2:
輸入:nums = [1], k = 1
輸出:[1]
示例 3:
輸入:nums = [1,-1], k = 1
輸出:[1,-1]
示例 4:
輸入:nums = [9,11], k = 2
輸出:[11]
示例 5:
輸入:nums = [4,-2], k = 2
輸出:[4]
分析:這是一道典型的滑動視窗問題,樸素的做法自然就是每個區間計算一次最大值,複雜度為o(nk)。如果讀者有學習過st表解決rmq問題的話,可以將此題的複雜度優化到o(nlogk)。我們首先來看看本題存在的多餘計算,以下圖為例:
在視窗為3的情況下,9在這三種情況下都存在,且是最大值,因此這三個區間,維護最大值就可以了,很多值是沒有必要維護的。
我們維護乙個單調佇列結構,一方面,我們保持整個佇列是單調遞減的,如果對頭元素已經不在當前的視窗內,則彈出;另一方面,當插入新元素時,如果隊尾比新元素小,則不斷彈出,直到佇列空或者隊尾元素大於新元素。
第一點相信很好理解,關鍵是第二點,為什麼可以彈出那些小的元素,事實上,由於我們是不斷向後遍歷的,因此我們不再需要考慮前面的區間,而後面的區間,會用到前面元素的可能性越來越低,越後面可能性越低,同時,一旦這些後面的區間包含了大的值,那麼舊的小值就不可能成為答案。
以題示為例:nums = [1,3,-1,-3,5,3,6,7], k = 3
初始化單調佇列時,我們只考慮前兩個元素,我們會得到單調隊列為:3
不保留1的原因在於,如果後面的區間包含了1,那麼勢必會包含3,而由於3的存在,那麼1自然就不可能為最大值,因此不需要保留他。
嘗試加入-1:-1<3,可以直接加入,佇列變為:3 -1
嘗試加入-3:-3
嘗試加入5:首先,對頭元素已經不在當前的區間內了,所以首先剔除,佇列變為:-1 -3,然後,根據單調性維護原則,佇列最終變為:5
後續請讀者自行嘗試。。。
class solution ;
vectormaxslidingwindow(vector& nums, int k)
window.push_back(node);
}for(; i < n; ++ i)
while( !window.empty() && i - window.front().index >= k )
window.push_back(node);
ans.push_back(window.front().value);
}return ans;}};
239 滑動視窗最大值
給定乙個陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗內的 k 個數字。滑動視窗每次只向右移動一位。返回滑動視窗中的最大值。示例 輸入 nums 1,3,1,3,5,3,6,7 和 k 3 輸出 3,3,5,5,6,7 解釋 滑動視窗的位置 最大...
239 滑動視窗最大值
239.滑動視窗最大值 solution deque solution maxindex 暴力法的時間複雜度為 o n k 弊端為每次掃瞄視窗的最大值,每兩次掃瞄之間都會存在重複的值比較,已經知道了他們的最大值是誰了,所以要減少比較次數 為什麼新增的是索引 將i加到隊尾 deque.addlast ...
239 滑動視窗最大值
給定乙個陣列 nums,有乙個大小為 k 的滑動視窗從陣列的最左側移動到陣列的最右側。你只可以看到在滑動視窗內的 k 個數字。滑動視窗每次只向右移動一位。返回滑動視窗中的最大值。高階 示例 輸入 nums 1,3,1,3,5,3,6,7 和 k 3 輸出 3,3,5,5,6,7 解釋 滑動視窗的位置...