zoukankan      html  css  js  c++  java
  • 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;
        }
    };
    
  • 相关阅读:
    extern C的作用详解
    UIWindow in iOS
    iOS会议和组织
    Fantageek翻译系列之《使用Autolayout显示变化高度的UITableViewCell》
    KVO的概述的使用
    Struts2 基于XML校验(易百教程)
    Maven项目中添加JDBC驱动
    org.dom4j.DocumentException: null Nested exception: null解决方法
    struts2中的数据类型自动转换
    struts2的拦截器
  • 原文地址:https://www.cnblogs.com/dacc123/p/12409995.html
Copyright © 2011-2022 走看看