【错题集-编程题】小葱的01串(滑动窗口)

牛客对应题目链接:小葱的01串 (nowcoder.com) 


一、分析题目

滑动窗口:长度固定的滑动窗口,因为要想符合要求,必定是⼀半⼀半的。

在选择区域时,仅需选择长度为字符串长度的一半即可。


二、代码

1、看了题解之后AC的代码

#include <iostream>
using namespace std;

int main()
{
    int n;
    cin >> n;
    string s;
    cin >> s;
    int zero=0, one=0;
    for(auto ch : s)
    {
        if(ch=='0') zero++;
        if(ch=='1') one++;
    }
    int res=0;
    int half=n/2;
    int zero_cnt=0, one_cnt=0;
    int left=0, right=0;
    while(right<n-1) //细节:防止重复计数
    {
        if(s[right]=='0') zero_cnt++;
        if(s[right]=='1') one_cnt++;
        while(right-left+1>half)
        {
            if(s[left]=='0') zero_cnt--;
            if(s[left]=='1') one_cnt--;
            left++;
        }
        if(right-left+1==half)
        {
            if(zero_cnt*2==zero && one_cnt*2==one)
                res+=2;
        }
        right++;
    }
    cout << res << endl;
    return 0;
}

2、值得学习的代码

#include <iostream>
#include <string>

using namespace std;

int n;
string s;

int main()
{
    cin >> n >> s;
    int sum[2] = { 0 }; // 统计字符串中所有 0 和 1 的个数
    for(auto ch : s)
    {
        sum[ch - '0']++;
    }
 
    int left = 0, right = 0, ret = 0, half = n / 2;
    int count[2] = { 0 }; // 统计窗⼝内 0 和 1 的个数
    while(right < n - 1) // 细节问题
    {
        count[s[right] - '0']++;
        while(right - left + 1 > half)
        {
            count[s[left++] - '0']--;
        }
        if(right - left + 1 == half)
        {
            if(count[0] * 2 == sum[0] && count[1] * 2 == sum[1])
            {
                ret += 2;
            }
        }
        right++;
    }
 
    cout << ret << endl;
 
    return 0;
}

三、反思与改进

这道题我一开始的做法是暴力解法,就是先统计字符串里面 0 和 1 的个数,因为题目明确说明了字符串的长度是偶数,所以再记录一下 0 和 1 数量的一半(这个是这道题的解题关键)。因为受到 “环形” 这一限制,我后面就想到了得用滑动窗口来解这道题,但是却忽略了一些细节,只过了 50% 的测试用例。在计算满足条件的连续区间数量时,没有考虑正确环形字符串的特性,所以即使我在字符串的末尾添加了一段和起始位置相同的字符串,但是我的循环仍然只考虑了从起始位置开始的子串,这就可能会导致遗漏一些解。

上面给出的代码不需要在字符串末尾添加字符,而是利用了字符串长度为偶数这一特性,一次+2,因为其中一半符合条件,那么剩下的一般一定也符合条件。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

炫酷的伊莉娜

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值