[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.








留言

這個網誌中的熱門文章

[面試心得] Synology / 群暉 - Product Developr

[面試心得] VICI Holdings / 威旭(高頻交易) - Software Engineer

[面試心得] GoFreight / 聖學科技(Freight Forwarder) - Full-Stack Engineer