LeetCode 239. Sliding Window Maximum(Hard)

题目

题意:在一个固定长度的滑动窗口里,计算窗口里的最大值,并且这个滑动窗口每次移动一个。

题解:首先想到的是set,窗口滑动,就是删除一个数,增加一个数,都是O(logn)的效率

80ms

class Solution {
public:
    multiset<int> m;
    vector<int> ans;
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        
        if(k==0||nums.size()==0)
            return ans;
        
        for(int i=0;i<k;i++)
        {
            m.insert(nums[i]);
        }
        
        ans.push_back(*prev(m.end()));
        
        for(int i=k;i<nums.size();i++)
        {
            multiset<int>::iterator it = m.find(nums[i-k]);
            m.erase(it);
            m.insert(nums[i]);
            ans.push_back(*prev(m.end()));
        }
        return ans;
    }
};

我们还可以用单调栈,实现在窗口滑动的过程中O(1)的效率得到最小值。
单调栈是一个单调递减的栈,入栈,也就是滑动时,如果栈顶元素比它小,则出栈,直到栈顶元素大于等于新元素。与此同时,栈低元素需要判断它的下标是否小于窗口左边,如果小于,栈底也要前进一格。
严格上来说,这也不是栈。
每次滑动窗口时,最大值显然是栈低元素,而进栈的操作,平均是O(1)的效率
60ms

class Solution {
public:
    int s1[100005];
    int s2[100005];
    int bottom1;
    int bottom2;
    int top1;
    int top2;
    vector<int> ans;
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        
        if(k==0||nums.size()==0)
            return ans;
        
        for(int i=0;i<k;i++)
        {
            EnStack(nums[i],i);
        }
        
        ans.push_back(s1[bottom1]);
        
        for(int i=k;i<nums.size();i++)
        {
            EnStack(nums[i],i);
            if(s2[bottom2]==i-k)
            {
                bottom2++;
                bottom1++;
            }
            
            ans.push_back(s1[bottom1]);
        }
        return ans;
    }
    
    void EnStack(int x,int pos)
    {
        if(top1==0)
        {
            s1[top1++]=x;
            s2[top2++]=pos;
        }
        else
        {
            while(top1!=bottom1&&s1[top1-1]<x)
            {
                top1--;
                top2--;
            }
            
            s1[top1++]=x;
            s2[top2++]=pos;
        }
    }
};

看了题解,发现还有更好的方法,就是实现维护两个数组,left数组表示窗口里从左开始的最大值,right数组表示从右开始的最大值。
52ms

class Solution {
public:
    int left[100005];
    int right[100005];
    vector<int> ans;
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        
        if(k==0||nums.size()==0)
            return ans;
        
        for(int i=0,j=nums.size()-1;i<nums.size()&&j>=0;i++,j--)
        {
            if(i%k==0)
                left[i]=nums[i];
            else
                left[i]=max(nums[i],left[i-1]);
            
            if((j+1)%k==0||j==nums.size()-1)
            {
                right[j]=nums[j];
            }
            else
                right[j]=max(nums[j],right[j+1]);
        }
        
        for(int i=0;i<nums.size()-k+1;i++)
        {
            ans.push_back(max(right[i],left[i+k-1]));
        }
        
        return ans;
    }
};
posted @ 2020-03-04 15:52  Shendu.CC  阅读(87)  评论(0编辑  收藏  举报