leetcode239. Maximum sliding window (difficult)

Keywords: array




I had no idea at first...
Solution 1: Violence
Specifically: the outer loop traverses the left position of the window, and the inner loop traverses the elements in the window
Analysis: the time complexity is O(nk) and n is the 5th power level, so it will timeout...
Thinking starting point: find a data structure to maintain the elements in the window. When the window slides to the right, delete the elements on the left from the data structure and add the elements on the right.

Solution 1: set
Note: there may be duplicate elements in the array, so you can't use set and change it to multiset!!!

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        //set may have duplicate elements. When deleting an element, it will be deleted!!!
        int n = nums.size();
        multiset<int> mst;
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            mst.insert(nums[i]);
        }
        ans.push_back(*st.rbegin());
        for (int i = 1; i <= n - k; ++i) {
            mst.erase(st.find(nums[i - 1]));
            mst.insert(nums[i + k - 1]);
            ans.push_back(*st.rbegin());
        }
        return ans;
    }
};

Solution 2: priority queue
Difficulty: it is impossible to delete the specified element (the element on the left after the window slides) from the heap. How to deal with it?
The solution is not to delete. Each time the maximum element is obtained, judge whether the heap top element is in the sliding window. If not, delete the heap top element until it is in the sliding window
Difficulty: so how to judge whether the stack top element belongs to the collection of elements in the window?
Solution 1: use hash to record the elements in the window (note that since there are duplicate elements in the array, the hash value records the number of occurrences of each element in the window, not whether it occurs!!!), and update the hash table every time the window is moved.
Solution 2: the type of elements in the heap is pair < int, int >, and second stores the subscript corresponding to the element in the array. Each time, compare the second of the element at the top of the heap with the left boundary of the window

Solution 1 Code: priority queue < int > + hash

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
	
        int n = nums.size();
        unordered_map<int, int> ump;
        priority_queue<int> pq;
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            pq.push(nums[i]);
            ump[nums[i]]++;
        }
        ans.push_back(pq.top());
        for (int i = 1; i <= n - k; ++i) {
            //Add new value
            pq.push(nums[i + k - 1]);
            ump[nums[i + k - 1]]++;
            ump[nums[i - 1]]--;
            if (!ump[nums[i - 1]]) ump.erase(nums[i - 1]);
            //Get the top of the heap (delete elements that are not in the window)
            while (!ump.count(pq.top())) pq.pop();
            ans.push_back(pq.top());
        }
        return ans;
    }
};

Solution 2 Code: priority queue < pair < int, int > >

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        //The priority queue does not use hash. The priority queue saves pair and second saves subscript
        int n = nums.size();
        priority_queue<pair<int, int>> pq;
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            pq.push(make_pair(nums[i], i));
        }
        ans.push_back(pq.top().first);
        for (int i = 1; i <= n - k; ++i) {
            //Join the team
            pq.push(make_pair(nums[i + k - 1], i + k - 1));
            //Stay out of the team until you get the top element
            while (pq.top().second < i) pq.pop();
            ans.push_back(pq.top().first);
        }
        return ans;
    }
};

Solution 3: monotone queue
Idea: maintain a single decreasing queue from the head of the team to the end of the team.
When inserting an element: if the end of the queue element is less than the value of the element, pop continuously_ Back() until the end of line element is greater than that element.
Get the team head element (maximum element): it may not be in the current window, and keep popping_ Front () until the queue header element appears in the window

Own code: pair < int is stored in the queue, and int > uses second to store subscripts. Second is compared with the left boundary of the window to judge whether it is in the sliding window
Optimization: since there is no sorting in the queue (unlike sorting in the heap above, you must use the second in pair to store the subscript), the value of the element can be obtained according to the subscript, so only the subscript is stored in the queue. The value of the corresponding element of the subscript from the head to the tail of the queue decreases step by step, and the required space is reduced by half!!!

class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        
        int n = nums.size();
        deque<int> dq; //Save only subscripts!!!
        vector<int> ans;
        for (int i = 0; i < k; ++i) {
            while (!dq.empty() && nums[dq.back()] < nums[i]) dq.pop_back();
            dq.push_back(i);
        }
        ans.push_back(nums[dq.front()]);
        for (int i = 1; i <= n - k; ++i) {
            //Add element
            while (!dq.empty() && nums[dq.back()] < nums[i + k - 1]) dq.pop_back();
            dq.push_back(i + k - 1);
            //Get maximum
            while (dq.front() < i) dq.pop_front();
            ans.push_back(nums[dq.front()]);
        }
        return ans;

    }
};

Posted by cnnabc on Sat, 06 Nov 2021 15:33:04 -0700