当前位置: 首页 > news >正文

滑动数组-定长滑动数组

题单顺序根据力扣的灵神大佬来的,思路也有借鉴灵神的,是一个自己的做题记录吧。会员题以后会补充更新,先发下不用会员的题。以后有新的相关题,我也会继续更新在这个文章中


目录

基础

1.定长子串中元音的最大数目

 2.子数组最大平均数 I

3.大小为 K 且平均值大于等于阈值的子数组数目

4.半径为 k 的子数组平均值

5.得到 K 个黑块的最少涂色次数

6.几乎唯一子数组的最大和

7.长度为 K 子数组中的最大和

8.可获得的最大点数

9.爱生气的书店老板

10.拆炸弹

进阶

1.检查一个字符串是否包含所有长度为 K 的二进制子串

2.最少交换次数来组合所有的 1

3.子串的最大出现次数

4.滑动子数组的美丽值

5.重新安排会议得到最多空余时间 I

6.使二进制字符串字符交替的最少反转次数

 7.字符串的排列

8.找到字符串中所有字母异位词

9.串联所有单词的子串

10.查找给定哈希值的子串

11. 统计完全子字符串

12. 子串能表示从 1 到 N 数字的二进制串


基础

1.定长子串中元音的最大数目

1456. 定长子串中元音的最大数目 - 力扣(LeetCode)

class Solution {
public:
    int maxVowels(string s, int k) {
        int cnt=0;
        int ans=0;
        unordered_map<char,int>mp;
        for(int i=0;i<s.length();i++)
        {
            cnt++;
            if(cnt>k)
            {
                ans=max(ans,mp['a']+mp['e']+mp['i']+mp['o']+mp['u']);
                mp[s[i-k]]--;
                mp[s[i]]++;
            }
            else{
                mp[s[i]]++;
            }
        }
        ans=max(ans,mp['a']+mp['e']+mp['i']+mp['o']+mp['u']);
        return ans;
    }
};

 2.子数组最大平均数 I

643. 子数组最大平均数 I - 力扣(LeetCode)

class Solution {
public:
    double findMaxAverage(vector<int>& nums, int k) {
        int cnt=0;
        int sum=0;
        double ans=-1e5;
        int n=nums.size();
        for(int i=0;i<n;i++){
            cnt++;
            if(cnt>k)
            {
                ans=max(ans,double(sum)/k);
                sum-=nums[i-k];
                sum+=nums[i];
            }
            else{
                sum+=nums[i];
            }
        }
        ans=max(ans,double(sum)/k);
        return ans;
    }
};

3.大小为 K 且平均值大于等于阈值的子数组数目

1343. 大小为 K 且平均值大于等于阈值的子数组数目 - 力扣(LeetCode)

class Solution {
public:
    int numOfSubarrays(vector<int>& arr, int k, int threshold) {
        int cnt=0;
        int sum=0;
        int ans=0;
        int n=arr.size();
        for(int i=0;i<n;i++)
        {
            cnt++;
            if(cnt>k)
            {
                if(double(sum)/k >=threshold){
                    ans++;
                }
                sum-=arr[i-k];
                sum+=arr[i];
            }
            else{
                sum+=arr[i];
            }
        }
        if(double(sum)/k >=threshold){
            ans++;
        }
        return ans;
    }
};

4.半径为 k 的子数组平均值

2090. 半径为 k 的子数组平均值 - 力扣(LeetCode)

class Solution {
public:
    vector<int> getAverages(vector<int>& nums, int k) {
        int left=0;
        long long sum=0;
        int n=nums.size();
        vector<int>ret(n,-1);
        for(int i=0;i<n;i++)
        {
            if(i-2*k<0)
            {
                sum+=nums[i];
                continue;
            }
            if(i-left+1==2*k+1)
            {
                sum+=nums[i];
                ret[i-k]=sum/(2*k+1);
                left++;
                sum-=nums[i-2*k];
            }
            else{
                sum+=nums[i];
            }
        }
        return ret;
    }
};

5.得到 K 个黑块的最少涂色次数

2379. 得到 K 个黑块的最少涂色次数 - 力扣(LeetCode)

class Solution {
public:
    int minimumRecolors(string blocks, int k) {
        int cnt=0;
        
        int ans=INT_MAX;
        int n=blocks.size();
        for(int i=0;i<n;i++)
        {
            if(i>=k)
            {
                ans=min(ans,cnt);
                cnt-= blocks[i-k]=='W'?1:0;
                cnt+=blocks[i]=='W'?1:0;
            }
            else{
                cnt+=blocks[i]=='W'?1:0;
            }
        }
        ans=min(ans,cnt);
        return ans;
    }
};

6.几乎唯一子数组的最大和

2841. 几乎唯一子数组的最大和 - 力扣(LeetCode)

class Solution {
public:
    long long maxSum(vector<int>& nums, int m, int k) {
        unordered_map<long long, long long> mp;
        int n = nums.size();
        long long cnt = 0;
        long long sum = 0;
        long long ans = 0;
        for (int i = 0; i < n; i++) {
            if (i >= k) {
                if (cnt >= m) {
                    ans = max(ans, sum);
                }
                sum -= nums[i - k];
                mp[nums[i - k]]--;
                cnt -= mp[nums[i - k]] == 0 ? 1 : 0;
                mp[nums[i]]++;
                sum+=nums[i];
                cnt += mp[nums[i]] == 1 ? 1 : 0;

            } else {
                sum += nums[i];
                mp[nums[i]]++;
                cnt += mp[nums[i]] == 1 ? 1 : 0;
            }
        }
        if (cnt >= m) {
            ans = max(ans, sum);
        }
        return ans;
    }
};

7.长度为 K 子数组中的最大和

2461. 长度为 K 子数组中的最大和 - 力扣(LeetCode)

class Solution {
public:
    long long maximumSubarraySum(vector<int>& nums, int k) {
        unordered_map<long long, long long> mp;
        int n = nums.size();
        int left = 0, right = -1;
        long long sum = 0, ans = 0;
        for (int i = 0; i < n; i++) {
            right++;
            if (right - left + 1 > k) {
                ans = max(ans, sum);
                mp[nums[left]]--;
                sum -= nums[left++];
            }
            mp[nums[right]]++;
            sum += nums[right];
            while (mp[nums[right]] > 1&&left<right) {
                sum -= nums[left];
                mp[nums[left]]--;
                left++;

            }
        }
        right++;
        if (right - left + 1 > k) {
            ans = max(ans, sum);
            sum -= nums[left++];
        }
        return ans;
    }
};

8.可获得的最大点数

1423. 可获得的最大点数 - 力扣(LeetCode)

class Solution {
public:
    int maxScore(vector<int>& cardPoints, int k) {
        int n=cardPoints.size();
        k=n-k;
        int sum=0,ans=INT_MAX;
        int ts=0;
        for(int i=0;i<n;i++)
        {
            ts+=cardPoints[i];
            sum+=cardPoints[i];
            if(i<k-1)continue;
            ans=min(ans,sum);
            sum-=cardPoints[i-k+1];
        }
        if(k==0)return ts;
        return ts-ans;
    }
};

9.爱生气的书店老板

1052. 爱生气的书店老板 - 力扣(LeetCode)

class Solution {
public:
    int maxSatisfied(vector<int>& customers, vector<int>& grumpy, int minutes) {
        int sum=0;
        int cnt=0;
        int ans=0;
        int n=customers.size();
        for(int i=0;i<n;i++)
        {
            if(grumpy[i]==0)cnt+=customers[i];
            sum+= grumpy[i]==1?customers[i]:0;
            if(i<minutes-1)continue;
            ans=max(ans,sum);
            sum-= grumpy[i-minutes+1]==1?customers[i-minutes+1]:0;
        }
        return cnt+ans;
    }
};

10.拆炸弹

1652. 拆炸弹 - 力扣(LeetCode)

class Solution {
public:
    vector<int> decrypt(vector<int>& code, int k) {
        int sum=0,n=code.size();
        vector<int>arr(n,0);
        if(k==0)return arr;
        int r= k>0?k:n-1;
        k=abs(k);
        sum=reduce(code.begin()+r-k+1,code.begin()+r+1);
        for(int i=0;i<n;i++)
        {
            r++;
            arr[i]=sum;
            sum+=code[(r)%n]-code[(r-k)%n];
        }
        return arr;
    }
};

进阶

1.检查一个字符串是否包含所有长度为 K 的二进制子串

1461. 检查一个字符串是否包含所有长度为 K 的二进制子串 - 力扣(LeetCode)

class Solution {
public:
    bool hasAllCodes(string s, int k) {
        long long cpy=pow(2,k);
        unordered_map<string,long long>mp;
        string cmp="";
        long long sum=0;
        long long n=s.size();
        for(int i=0;i<n;i++)
        {
            cmp+=s[i];
            if(i<k-1)continue;
            if(++mp[cmp.substr(i-k+1,k)]==1)sum++;
        }
        if(sum==cpy)return true;
        else return false;
    }
};

2.最少交换次数来组合所有的 1

2134. 最少交换次数来组合所有的 1 II - 力扣(LeetCode)

class Solution {
public:
    int minSwaps(vector<int>& nums) {
        int cpy = reduce(nums.begin(), nums.end());
        int sum = 0, n = nums.size();
        int ncpy = n - cpy;
        int ans1 = INT_MAX, ans2 = INT_MAX;
        if (cpy != 0) {
            for (int i = 0; i < n; i++) {
                sum += nums[i];
                if (i < cpy - 1)
                    continue;
                ans1 = min(ans1, cpy - sum);
                sum -= nums[i - cpy + 1];
            }
        }
        sum = 0;
        if (ncpy != 0) {
            for (int i = 0; i < n; i++) {
                sum += nums[i];
                if (i < ncpy - 1)
                    continue;
                ans2 = min(ans2, sum);
                sum -= nums[i - ncpy + 1];
            }
        }
        return min(ans1, ans2);
    }
};

3.子串的最大出现次数

1297. 子串的最大出现次数 - 力扣(LeetCode)

class Solution {
public:
    int maxFreq(string s, int maxLetters, int minSize, int maxSize) {
        int ans=0,cnt=0,n=s.size();
        unordered_map<string,int>mp;
        unordered_map<char,long long>pp;
        string tmp;
        for(int i=0;i<n;i++)
        {
            tmp+=s[i];
            if(++pp[s[i]]==1)cnt++;
            if(i<minSize-1)continue;
            cout<<tmp<<" "<<cnt;
            if(cnt<=maxLetters){
                ans=max(ans,++mp[tmp]);
            }
            cnt-=--pp[s[i-minSize+1]]==0?1:0;
            tmp.erase(tmp.begin());
        }
        return ans;
    }
};

这个要注意,核心就是不要被maxsize给误导了,因为在[minsize+1,maxsize]这个长度区间,子串的重复次数,肯定小于等于长度minsize的子串重复次数,比如'abcabcdfabcabc',在这里,abcabc这个子串重复了2次,abc重复了4次。

4.滑动子数组的美丽值

2653. 滑动子数组的美丽值 - 力扣(LeetCode)

class Solution {
public:
    vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
        map<long long,long long>mp;
        int n=nums.size();
        vector<int>ans(n-k+1,0);
        for(int i=0;i<n;i++)
        {
            mp[nums[i]]++;
            if(i<k-1)continue;
            int cnt=0;
            for(auto &c:mp)
            {
                cnt+=c.second;
                if(cnt>=x)
                {
                    ans[i-k+1]=c.first<0?c.first:0;
                    break;
                }
            }
            mp[nums[i-k+1]]--;
        }
        return ans;
    }
};

但这题可以直接开数组,不用容器,容器遍历复杂度有点高。

class Solution {
public:
    
    vector<int> getSubarrayBeauty(vector<int>& nums, int k, int x) {
        const int N=1e5;
        int mp[2*N+1];
        memset(mp,0,sizeof(mp));
        int n=nums.size();
        vector<int>ans(n-k+1,0);
        for(int i=0;i<n;i++)
        {
            mp[nums[i]+51]++;
            if(i<k-1)continue;
            int cnt=0;
            for(int j=0;j<N+52;j++)
            {
                cnt+=mp[j];
                if(cnt>=x)
                {
                    ans[i-k+1]=j-51<0?j-51:0;
                    break;
                }
            }
            mp[nums[i-k+1]+51]--;
        }
        return ans;
    }
};

暴力搜索,正解应该懒删除堆法。

5.重新安排会议得到最多空余时间 I

3439. 重新安排会议得到最多空余时间 I - 力扣(LeetCode)

class Solution {
public:
    int get(int i,int eventTime,vector<int>& startTime, vector<int>& endTime)
    {
        int n=startTime.size();
        if(i==0){
                return startTime[0]-0;
            }
            else if(i==n)
            {
                return eventTime-endTime[n-1];
            }
            return startTime[i]-endTime[i-1];
    }
    int maxFreeTime(int eventTime, int k, vector<int>& startTime, vector<int>& endTime) {
        int sum=0,n=startTime.size();
        int ans=0;
        for(int i=0;i<=n;i++)
        {
            sum+=get(i,eventTime,startTime,endTime);
            if(i<k)continue;
            ans=max(ans,sum);
            sum-=get(i-k,eventTime,startTime,endTime);
        }
        return ans;
    }
};

思路一下子想不出来,看了灵神的思路。一开始想着那边lambda函数没必要,后面写着,才知道,不用函数压根不好写条件。但lambda看着还是比较抽象的,我写了普通的函数。但lambda确实方便。

6.使二进制字符串字符交替的最少反转次数

1888. 使二进制字符串字符交替的最少反转次数 - 力扣(LeetCode)

空间未优化

class Solution {
public:
    int minFlips(string s) {
        
        int sum=0,n=s.size(),ans=INT_MAX;
        char prev='1';
        s+=s;
        for(int i=0;i<2*n;i++)
        {
            sum+=s[i]==prev?1:0;
            prev=prev=='1'?'0':'1';
            if(i<n-1)continue;
            ans=min({ans,sum,n-sum});
            char par;
            if(n%2!=0){
                par=prev;
            }
            else{
                par=prev=='1'?'0':'1';
            }
            
            sum-=(s[i-n+1]==par?0:1);
        }
        return ans;
    }
};

时间复杂度:O(N),空间复杂度:O(N)

精选的题解讲的太简略了,灵神的那个看着有点复杂。

我看了好多篇题解,发现这样写是挺好的。

核心:通过双倍字符串,结合滑动窗口,可以遍历所有可能得组合字符串。具体的可以看精选的题解的图解部分。

prev是位置i正确的字符。

需要明白的点:检测10串得到的次数,等于s长度-检查01串得到的次数 的次数。

因此开局选择其中一个作为prev即可。以下以01串开始。

i与prev比较即可,相同就增加次数。

如果n为奇数,以i-n+1为开始的滑动窗口,可以复原得到,i-n+1位置的正确字符应该是跟当前i位置的正确字符相等。

而如果n偶数数,则相反即可,比如0101。

优化下空间。

class Solution {
public:
    int minFlips(string s) {
        
        int sum=0,n=s.size(),ans=INT_MAX;
        char prev='1';
        //s+=s;
        for(int i=0;i<2*n;i++)
        {
            sum+=s[i%n]==prev?1:0;
            prev=prev=='1'?'0':'1';
            if(i<n-1)continue;
            ans=min({ans,sum,n-sum});
            char par;
            if(n%2!=0){
                par=prev;
            }
            else{
                par=prev=='1'?'0':'1';
            }
            
            sum-=(s[(i-n+1)%n]==par?0:1);
        }
        return ans;
    }
};

时间复杂度:O(N),空间复杂度:O(1)

更优秀的答案,遍历长度达不到2*n,但我个人能力有限,基于我目前的代码,还不知道该怎么优化。

有兴趣的可以自己试试

 7.字符串的排列

567. 字符串的排列 - 力扣(LeetCode)

class Solution {
public:
    bool checkInclusion(string s1, string s2) {
        unordered_map<char, int> pare;
        int cnt = 0;
        int n = s2.size(), k = s1.size();
        for (auto& x : s1) {
            pare[x]++;
        }
        unordered_map<char, int> mp;
        for (int i = 0; i < n; i++) {
            mp[s2[i]]++;
            if (mp[s2[i]] <= pare[s2[i]])
                cnt++;
            if (i < k - 1)
                continue;
            if (cnt == k)
                return true;
            if (mp[s2[i - k + 1]] <= pare[s2[i - k + 1]])
                cnt--;
            mp[s2[i - k + 1]]--;
        }
        return false;
    }
};

8.找到字符串中所有字母异位词

438. 找到字符串中所有字母异位词 - 力扣(LeetCode)

class Solution {
public:
    int pare[26],mp[26];
    vector<int> findAnagrams(string s, string p) {
        
        for(auto &x:p)pare[x-'a']++;
        int n=s.size(),k=p.size();
        int cnt=0;vector<int>ret;
        for(int i=0;i<n;i++)
        {
            if(++mp[s[i]-'a']<=pare[s[i]-'a'])cnt++;
            if(i<k-1)continue;
            if(cnt==k)ret.push_back(i-k+1);
            if(mp[s[i-k+1]-'a']--<=pare[s[i-k+1]-'a'])cnt--;
        }
        return ret;
    }
};

一开始想着用unordered_map的,后面发现,只有小写字母,那开个数组就够了。

9.串联所有单词的子串

30. 串联所有单词的子串 - 力扣(LeetCode)

class Solution {
public:
    vector<int> findSubstring(string s, vector<string>& words) {
        unordered_map<string, int> pare, mp;
        for (auto& x : words) {
            pare[x]++;
        }
        auto check = [&]() {
            for (auto& x : pare) {
                if (!mp.count(x.first))
                    return false;
                if (mp[x.first] != x.second)
                    return false;
            }
            return true;
        };
        int n = s.size(), k = words.size(), p = words[0].size();
        vector<int> ret;
        for (int t = 0; t < p; t++) {
            mp.clear();
            for (int i = t+p-1; i < n; i+=p) {
                string tmp=s.substr(i-p+1,p);
                mp[tmp]++;
                if(i<t+p*k-1)continue;
                if(check())ret.push_back(i-p*k+1);
                string cp=s.substr(i-p*k+1,p);
                mp[cp]--;
            }
        }
        return ret;
    }
};

10.查找给定哈希值的子串

2156. 查找给定哈希值的子串 - 力扣(LeetCode)

class Solution {
public:
    string subStrHash(string s, int power, int modulo, int k, int hashValue) {
        int n = s.size();
        long long hash = 0, pk = 1;
        long long ans=0;
        for (int i = n - 1; i >= 0; i--) {
            if (i >= n - k) {
                hash = (hash * power + (s[i] - 'a' + 1))%modulo;
                pk *= power;
                pk%=modulo;
                if(i==n-k&&hash==hashValue)ans=i;
            } else
            {
                hash=(hash*power+(s[i]-'a'+1)-pk*(s[i+k]-'a'+1)%modulo+modulo)%modulo;
                if(hash==hashValue)ans=i;
            }
        }
        return s.substr(ans,k);
    }
};

这题重点不是滑动窗口,核心是秦九韶算法对多项式计算的优化,配合从右往左的滑动窗口完成本题。思路是看灵神的。

11. 统计完全子字符串

2953. 统计完全子字符串 - 力扣(LeetCode)

class Solution {
public:
    int cnt[26];
    int func(const string&s,int k)
    {
        int n=s.size();
        int res=0;
        auto check=[&](){
            for(auto &x:cnt)
            {
                if(x>0&&x!=k)return;
            }
            res++;
        };
        for(int i=1;i<=26&&i*k<=n;i++)
        {
            memset(cnt,0,sizeof (cnt));
            for(int j=0;j<n;j++)
            {
                cnt[s[j]-'a']++;
                if(j<i*k-1)continue;
                check();
                cnt[s[j-i*k+1]-'a']--;
            }
        }
        return res;
    }
    int countCompleteSubstrings(string word, int k) {
        //分组循坏,通过第二个条件,先划分多个区间段,每个区间串计算其满足条件1的子串数量
        //最后把所有区间段的结果累加起来,就是最终答案。

        //分组循坏
        int n=word.size();
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int start=i;
            for(i++;i<n;i++)
            {
                if(abs(int(word[i])-int(word[i-1]))>2)break;
            }
            i--;
            ans+=func(word.substr(start,i-start+1),k);
        }
        return ans;
    }
};

这份是O(26*26*n)复杂度,思路是灵神那边提供的,我只能说我自己看懂了吧。

下面是时间复杂度继续优化的结果。

class Solution {
public:
    int cnt[26];
    static const int N=1e5+1;
    int pt[N];
    int func(const string&s,int k)
    {
        int n=s.size();
        int res=0;
        for(int i=1;i<=26&&i*k<=n;i++)
        {
            memset(pt,0,sizeof pt);
            memset(cnt,0,sizeof (cnt));
            for(int j=0;j<n;j++)
            {
                pt[cnt[s[j]-'a']]--;
                cnt[s[j]-'a']++;
                pt[cnt[s[j]-'a']]++;
                if(j<i*k-1)continue;
                if(pt[k]==i)res++;
                pt[cnt[s[j-i*k+1]-'a']]--;
                cnt[s[j-i*k+1]-'a']--;
                pt[cnt[s[j-i*k+1]-'a']]++;
            }
        }
        return res;
    }
    int countCompleteSubstrings(string word, int k) {
        //分组循坏,通过第二个条件,先划分多个区间段,每个区间串计算其满足条件1的子串数量
        //最后把所有区间段的结果累加起来,就是最终答案。

        //分组循坏
        int n=word.size();
        int ans=0;
        for(int i=0;i<n;i++)
        {
            int start=i;
            for(i++;i<n;i++)
            {
                if(abs(int(word[i])-int(word[i-1]))>2)break;
            }
            i--;
            ans+=func(word.substr(start,i-start+1),k);
        }
        return ans;
    }
};

复杂度优化到了O(26*n);

但要浪费一个O(n)的空间。用哈希的话速度太慢了,哈希查询很快,但是清空或者创建,比较费时间。

12. 子串能表示从 1 到 N 数字的二进制串

1016. 子串能表示从 1 到 N 数字的二进制串 - 力扣(LeetCode)

暴力做法

class Solution {
public:
    bool queryString(string s, int n) {
        for(int i=1;i<=n;i++)
        {
            auto tmp=bitset<32>(i).to_string();
            //这个是bitset的初始化用法
            //这里是创建了个匿名的bitset对象,这个对象可以存32位数字
            //将i转换成二进制数存入这个匿名对象,然后再利用to_string()
            //把这个对象存的二进制数以字符串的形式展现出来。
            int index=tmp.find('1');
            if(s.find(tmp.substr(index))==-1)return false;
        }
        return true;
    }
};

这个做法,我一开始下意思是不想做的,我刚开始下意思想的是下面的一个版本,直到看见灵神的题解,才发现暴力竟然也能过。复杂度的解析我这里就不赘述了,灵神讲的很详细了。时间复杂度:O(min(m,n)⋅mlogmin(m,n))。空间复杂度:O(logn)

-------------------------------------------------------------------------------------------

接下来是我一开始想的思路,不过我一开始就只想到了要把s的所有子串转换成数字存起来,

但是当时觉得会超时,因为每次都要以i为起点,往后找子串,但是看了灵神的分析,每次的起点只需要在1的位置即可,并且当转换的数字大于n,就可以break掉,每个起点只需要遍历logn次即可。

class Solution {
public:
    bool queryString(string s, int n) {
        int m=s.size();
        unordered_set<int>mp;
        for(int i=0;i<m;i++)
        {
            if(s[i]=='0')continue;
            int sum=s[i]-'0';
            mp.insert(sum);
            for(int j=i+1;j<m&&sum<=n;j++)
            {
                sum=(sum<<1)|(s[j]-'0');//看灵神学会的,很妙
                if(sum<=n)mp.insert(sum);
            }
        }
        return mp.size()==n;
    }
};

我尝试过代码是否可以写得更加简洁,但发现改不了。只能换一下,代码量差不多。

--------------------------------------------------------------

灵神还有一份解法,这个解法,这个思路是主要是基于灵神对算法1复杂度解析之后得出的结果。不推荐写,虽然复杂度很低,是线性的复杂度,O(m),但思考过程有点点非人了。

下面是我仿照灵神写的,主要是加了些解释性的话。思路分析可以看灵神的。

class Solution {
public:
    bool queryString(string s, int n) {
        if(n==1)return s.find("1") !=-1;
        int m=s.size();
        int k=31-__builtin_clz(n);//这个函数用于计算一个整数的二进制表示中,
        //从最高位开始连续的0的个数。这样的结果就是n的有效二进制长度-1,省去无意义的0
        if(m<max(n-(1<<k)+k+1,(1<<(k-1))+k-1))return false;
        //这个是分析得到的一个结论,具体可看灵神的分析
        //下面是对长为k的在[left,right]内的二进制数,判断这些数s是否都有
        auto check=[&](int k,int left,int right)->bool {
            if(left>right)return true;
            unordered_set<int>seen;
            int mask=(1<<(k-1))-1;//这个是用来抹除最高bit位的。
            //也就是k-2位全为1的二进制数
            int x=stoi(s.substr(0,k-1),nullptr,2);
            //把前k-1个二进制数转换成10进制

            //开始进行滑动窗口,遍历子串
            for(int i=k-1;i<m;i++)
            {
                x=((x&mask)<<1)|(s[i]-'0');
                //x&mask,就是用k-1个二进制数与k-2个1进行与操作,从而去掉最高位
                //后面的操作,就是滑动窗口的入操作,这个很好懂,左移1位,再与一下
                if(left<=x&&x<=right)
                {
                    seen.insert(x);
                }
            }
            return seen.size()==right-left+1;
        };
        return check(k,n/2+1,(1<<k)-1)&&check(k+1,1<<k,n);
        //这个也是分析的结论,我虽然看懂了,但是讲还是有点讲不明白的,有兴趣看灵神的分析。
        
    }
};

相关文章:

  • SSH无法使用root用户进行登陆的解决方法
  • 【HarmonyOS Next】鸿蒙应用实现弹框DialogHub详解
  • Excel(函数进阶篇):Vlookup函数进阶、TAKE嵌套SORE函数、SUBTOTAL函数、INDIRECT函数
  • 华为全流程全要素研发项目管理(81页PPT)(文末有下载方式)
  • 蓝桥杯练习day1:拆分数位-四位数字的最小和
  • 【深度解析】48V转24V/5A宽压电源芯片:SOT23-5封装+外挂MOS管应用方案
  • rust学习笔记17-异常处理
  • 《心理学与生活》2025最新网课答案
  • Python的Pytest(2)
  • C语言 常用系统函数
  • 蓝桥云客 找素数
  • reconstruct_3d_object_model_for_matching例子
  • C# WPF编程-Menu
  • 戴尔系列电脑安装UBUNTU系统
  • MySQL事务:确保数据一致性的关键机制
  • fastapi+angular宠物领养系统
  • 基于Nvidia Jetson Nano边缘计算设备使用TensorRT部署YOLOv8模型实现目标检测推理
  • 基于Python+Ollama DeepSeek与MySQL进行数据分析探索
  • apache-maven-3.9.9 详细安装配置教程(2025版)
  • 贪心算法作业参考:P1106,P4995,P5019
  • 张国清将赴俄罗斯举行中俄“长江—伏尔加河”地方合作理事会第五次会议和“东北—远东”政府间合作委员会双方主席会晤
  • 自强!助残!全国200个集体和260名个人受到表彰
  • 上海高院与上海妇联签协议,建立反家暴常态化联动协作机制
  • 国防部:菲方应停止一切侵权挑衅危险举动,否则只会自食苦果
  • 中国—美国经贸合作对接交流会在华盛顿成功举行
  • 国新办将就2025年4月份国民经济运行情况举行新闻发布会