Skip to content

双指针之滑动指针

About 642 wordsAbout 2 min

基础算法

2024-07-09

代码随想录管这叫滑动窗口,但是我想区别于单调队列的滑动窗口,自命名为滑动指针!

代码随想录 (programmercarl.com)

滑动指针

滑动指针一般用于求符合某种条件的最长或最短的子序列

在暴力解法中,是一个for循环滑动窗口的起始位置,一个for循环为滑动窗口的终止位置,用两个for循环完成了一个不断搜索区间的过程,时间复杂度为O(n2)O(n^2)

而滑动指针,就是不断的调节子序列的起始位置和终止位置,维护窗口的状态,从而得出我们要想的结果,时间复杂度为O(n)O(n)

滑动指针的实现需要考虑如下问题:

  • 如何移动窗口的起始位置?

  • 如何移动窗口的结束位置?

  • 维护哪些数据?

题目

209.长度最小的子数组

  1. 初始时,起始指针和终止指针都位于序列首元素
  2. 终止指针不断后移直到子序列的和大于target,更新子序列和
  3. 起始指针不断后移直到子序列的和小于target,更新子序列和与最小长度
  4. 重复2和3,直到终止指针到达序列末尾
class Solution {
public:
    int minSubArrayLen(int target, vector<int>& nums) {
        int i=0,j=0,s=0,ans=0x3f3f3f3f;
        while(j<nums.size()){
            s+=nums[j++];
            while(s>=target && i<j){
                ans=ans<=(j-i)?ans:(j-i);
                s-=nums[i++];
            }
        }
        if(ans==0x3f3f3f3f) return 0;
        else return ans;
    }
};

904.水果成篮

  1. 初始时,起始指针和终止指针都位于序列首元素。用两个变量记录当前选择的水果种类,初始化为-1。
  2. 终止指针不断后移直到遇到未记录的水果种类,更新两个用于记录的变量
  3. 起始指针从终止指针前向前移动直到遇到不一样的水果种类,更新最大数目
  4. 重复2和3,直到终止指针到达序列末尾
class Solution {
public:
    int totalFruit(vector<int>& fruits) {
        if(fruits.size()<=2) return fruits.size();
        int i=0,j=0,ans=2;
        int h=-1,t=-1;
        for(;j<fruits.size();j++){
            if(fruits[j]!=h && fruits[j]!=t){
                if(h==-1) h=fruits[j];
                else if(t==-1) t=fruits[j];
                else{
                    ans=ans>=(j-i)?ans:(j-i);
                    h=fruits[j-1];
                    t=fruits[j];
                    i=j-1;
                    while(i>=0 && fruits[i]==h) i--;
                    i++;
                }
            }
        }
        return ans>=(j-i)?ans:(j-i);
    }
};

76.最小覆盖子串

(未完成)