[LeetCode][Hard] 239. Sliding Window Maximum
Leetcode 網址: https://leetcode.com/problems/sliding-window-maximum/
題目說明:
給定一個沒有排列長度為 n 的陣列與窗口大小 k ( 1 <=k <= n),
每次窗口會往右移動一格,直到窗口大小超出陣列長度,
請找出移動過程中窗口範圍內的最大值。
解題說明:
這題最暴力法直接做就是每次從大小為 k 窗口中找最大元素,
由於 n 可能等於 n / 2,所以暴力法的時間複雜度為 O (n^2)。
接著再來思考比較好的做法就是 Max Heap,
Max Heap 插入跟刪除的時間複雜度皆為 O (log n),
由於插入跟刪除最多為 n 次,所以其時間複雜度可以壓到 O (n log n) ~
後來解完題目後,看了下討論區有種 O (n) 的解法是用 double-ended queue,
其算法概念是每次新增元素到 queue 前,把那些沒有用的元素先 pop 掉,
例如: 4 3 2 1 7 來說,當我們要新增 7 的時候就把前面的 pop 掉,
原因是往右邊移動的話, 4 3 2 1 這幾個數字絕對不可能是最大值,
所以有以上想法後就可以解決此題啦!
程式碼 (Max Heap)
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
vector<int> result;
priority_queue<pair<int, int>> pq;
for (int i = 0; i < nums.size(); i++) {
while (i >= k && pq.size() > 0 && i - k >= pq.top().second) pq.pop();
pq.push(pair(nums[i], i));
if (i >= k - 1) result.push_back(pq.top().first);
}
return result;
}
};
程式碼 (Double-ended queue)
class Solution {
public:
vector<int> maxSlidingWindow(vector<int>& nums, int k) {
deque<int> dq;
vector<int> result;
for (int i = 0; i < nums.size(); i++) {
if (!dq.empty() && i - k == dq.front()) dq.pop_front();
while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back();
dq.push_back(i);
if (i >= k - 1) result.push_back(nums[dq.front()]);
}
return result;
}
};
結果
Runtime: 216 ms, faster than 98.61% of C++ online submissions for Sliding Window Maximum.
Memory Usage: 118.7 MB, less than 52.05% of C++ online submissions for Sliding Window Maximum.
留言
張貼留言