LeetCode Day8 滑动窗口

467 环绕字符串中唯一的子字符串

题目理解

①S是个“a~z”无限环绕的字符串,参数中也没有显式给出S。
②给定字符串p,寻找s中p的不同子串,即p的子串数目,注意子串,即要求连续。

思路

首先,p的子串怎样在S中找到,要注意到S中的相邻字符有两种情况,一是差值为1,另一种是z和a相邻。
如果p非空,以“bzab”为例,显然p[0]=b一定是一个子串,再接着看p[1]=z,p[1]不满足上述两种情况,则“bz”不是子串,"z"为子串,接着p[2]=a,满足条件,则增加的子串为“a”,“za”,接着p[3]=b,满足条件,增加的子串为“b”,“ab”,“zab”。我们可以发现在连续满足条件的情况下,一个字符增加子串数为1,两个增加数为2,3个为3…,因此我们考虑用pre来记录当前增加的子串数,同时pre也是以当前p[i]为尾的子串数。循环判断,初始pre设置为1(因为单个字符必构成子串),只要满足条件,pre+1,不满足条件,pre重置为1,将所有的pre累加即为结果。
题目中要求的是子串的种类数,上述的pre是所有的子串数,可以使用哈希表记录以p[i]为尾的子串数,例如“bzab”,以z为尾的子串数为1,a为2,b为3,结果即为1+2+3=6.

代码

class Solution {
public:
    int findSubstringInWraproundString(string p) {
        int n=p.size();
        unordered_map<char,int> hash;
        int count=0;
        int pre=1;
        if(n){
            hash[p[0]]=pre;
            for(int i=1;i<n;i++){
                if(p[i]-p[i-1]==1||p[i-1]-p[i]==25)
                    pre+=1;
                else 
                    pre=1;
                hash[p[i]]=max(hash[p[i]],pre);
            }
            for(auto c:hash)
                count+=c.second;
        }else 
            return 0;
        return count;
    }
};

795 区间子数组个数

题目理解

给定数组A,L,R,求的是满足子数组中最大元素满足>=L&&<=R,要注意只要最大元素满足条件即可,且子数组元素要连续。

思路

先考虑如果要求最大元素满足<=R的情况,和上题思路类似,以[2, 1, 4, 3]为例,假设R=4,首先2<4,增加子数组为{2};接着1<4,增加的子数组为{1},{2,1};接着4=4,增加子数组为{4},{1,4},{2,1,4},同理3增加的子数组为{3},{4,3},{1,4,3},{2,1,4,3}。
但这只考虑了最大元素小于等于R的情况,最大元素还要满足大于等于L。因为最大元素满足<=R一定包含最大元素<L的情况(要注意是<),只要将最大元素小于L的子数组从中剔除掉,剩下的就是最大元素大于等于L小于等于R的子数组。
题目中对字数组的判断可能是根据数组索引,因此即使数组元素相同但下标不同也为不同的子数组,例如{2,2}结果为3。

代码

class Solution {
public:
    int numSubarrayBoundedMax(vector<int>& A, int L, int R) {
        int preL=0,preR=0;
        int n=A.size();
        int numL=0,numR=0;
        for(int i=0;i<n;i++){
            if(A[i]<L)
                preL+=1;
            else preL=0;
            numL+=preL;
        }
        for(int i=0;i<n;i++){
            if(A[i]<=R)
                preR+=1;
            else preR=0;
            numR+=preR;
        }
        return numR-numL;
    }
};

904 水果成篮

题目理解

通俗讲,每个篮子只携带一种类型的水果,两个篮子,也就是子数组中只有两种元素,能收集到的水果树的最大总量,也就是,最长子数组。

思路

还是寻找最长连续子数组的问题,不过是加上了只能有两种元素的限定条件。用哈希表来储存当前子数组中的元素数,结果为哈希表的尺寸为2时的最大元素数。
滑动窗口的思想是右指针先递增,也就是增大滑动窗口长度,直到不满足哈希表尺寸为2,在这之前得到的是左指针固定在0位置时的最长子数组,这就是当前右指针之前的最长子数组;接着递增左指针,即缩小滑动窗口长度直到再次满足条件,这是当前右指针的最长子数组,继续循环直到遍历完数组。

代码

class Solution {
public:
    int totalFruit(vector<int>& tree) {
        int n=tree.size();
        int res=0;
        unordered_map<int,int> hash;
        for(int L=0,R=0;R<n;R++){
            hash[tree[R]]++;
            while(hash.size()>2){
                hash[tree[L]]--;
                if(hash[tree[L]]==0)
                    hash.erase(tree[L]);
                L++;
            }
            res=max(res,R-L+1);
        }
        return res;
    }
};

992 K个不同整数的子数组

题目理解

给定数组A和K,求的是正好有K种整数的子数组。

思路

与795题类似,求出当子数组中的元素种类小于等于K时子数组数,再求出当子数组中的元素种类小于等于K-1时子数组数,即为所求。

代码

class Solution {
public:
    int mostK(vector<int>& A, int K)
    {
        int n=A.size();
        int res=0;
        unordered_map<int,int> hash;
        for(int L=0,R=0;R<n;R++){
            ++hash[A[R]];
            while(hash.size()>K){
                --hash[A[L]];
                if(hash[A[L]]==0)
                    hash.erase(A[L]);
                ++L;
            }
            res+=R-L+1;
        }
        return res;
    }
    int subarraysWithKDistinct(vector<int>& A, int K) {
        return mostK(A,K)-mostK(A,K-1);
    }
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值