滑动窗口

地址:1.滑动窗口最大值 - 力扣

思路:我们维护一个双向单调队列,队列放的是元素的下标。我们假设该双端队列的队头是整个队列的最大元素所在下标,至队尾下标代表的元素值依次降低。初始时单调队列为空。随着对数组的遍历过程中,每次插入元素前,首先需要看队头是否还能留在队列中,如果队头下标距离i超过了k,则应该出队。同时需要维护队列的单调性,如果nums[i]大于或等于队尾元素下标所对应的值,则当前队尾再也不可能充当某个滑动窗口的最大值了,故需要队尾出队。始终保持队中元素从队头到队尾单调递减。依次遍历一遍数组,每次队头就是每个滑动窗口的最大值所在下标。

JAVA:

复制代码
class Solution {
    public int[] maxSlidingWindow(int[] nums, int k) {
 Deque<Integer> q=new LinkedList<>();
        if(nums.length==0)
        {
            return nums;
        }
        int[] ans=new int[nums.length-k+1];
        int cnt=0;
        for(int i=0;i<nums.length;i++)
        {
            while(!q.isEmpty()&&i-q.peekFirst()>=k)
            {
                q.pollFirst();
            }
            while(!q.isEmpty()&&nums[i]>=nums[q.peekLast()])
            {
                q.pollLast();
            }
            q.offerLast(i);
            if(i>=k-1)
            {
                    ans[cnt++]=nums[q.peekFirst()];
            }
        }
        return ans;

    }
}
View Code
复制代码

C++(STL):

复制代码
class Solution {
public:
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
        if(nums.size()==0)
        {
            return nums;
        }
 vector<int> res;
      deque<int> q;
      for(int i=0;i<nums.size();i++)
      {
          while(q.size()&&(i-q.front()>=k))
          {
              q.pop_front();
          }
          while(q.size()&&nums[i]>=nums[q.back()])
          {
              q.pop_back();
          }
          q.push_back(i);
          if(i>=k-1)
          {
              res.push_back(nums[q.front()]);
          }
      }
      return res;
    
    }
};
View Code
复制代码

C++(模拟队列:

复制代码
class Solution {
public: int q[100010];
    vector<int> maxSlidingWindow(vector<int>& nums, int k) {
      
        if(nums.size()==0)
        {
            return nums;
        }
        vector<int> ans;
       
        int hh=0;
        int tt=0;
        for(int i=0;i<nums.size();i++)
        {
            while(hh<=tt&&i-q[hh]>=k)
            {
                hh++;
            }
            while(hh<=tt&&nums[q[tt]]<=nums[i])
            {
                tt--;
            }
            q[++tt]=i;
            if(i>=k-1)
            {
            ans.push_back(nums[q[hh]]);
            }
        }
        return ans;
        
      }
};
View Code
复制代码

 2. 字符串的排列 - 力扣(LeetCode) (leetcode-cn.com)

思路:将s1的长度当做滑动窗口,每次一进一出,利用变量diff记录s1与s2不同字符的个数,判断diff是否为0

代码:

复制代码
   public boolean checkInclusion(String s1, String s2) {
      int n=s1.length();
      int m=s2.length();
      if(n>m)
      {
          return false;
      }
      int[] cnt=new int[27];
      //cnt为cnt(s2)-cnt(s1)
      for(int i=0;i<n;i++)
      {
          --cnt[s1.charAt(i)-'a'];
          ++cnt[s2.charAt(i)-'a'];

      }
      int diff=0;
      for(int c:cnt)
      {
          if(c!=0)
          {
              ++diff;
          }
      }
      if(diff==0)
      {
          return true;
      }
      for(int i=n;i<m;i++)
      {
          int x=s2.charAt(i)-'a';//要出去的字符
          int y=s2.charAt(i-n)-'a';//要进来的字符
          if(x==y)
          {
              continue;
          }
        if(cnt[x]==0)//若未出去前该字符的差值为0 说明两个字符串该字符个数相等
        {
            ++diff;//出去则需要将diff+1
        }
        ++cnt[x];//多的字符
        if(cnt[x]==0)
        {
            --diff;
        }
        if(cnt[y]==0)//要进入的字符...
        {
            ++diff;
        }
        --cnt[y];
        if(cnt[y]==0)
        {
            --diff;
        }

    if(diff==0)
    {
        return true;
    }


      }
      return false;


    }

}
View Code
复制代码

 

posted @   blakee  阅读(146)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
· 单元测试从入门到精通
· 上周热点回顾(3.3-3.9)
· winform 绘制太阳,地球,月球 运作规律
点击右上角即可分享
微信分享提示