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

 题解链接(可跳转做题)

点击上方即可

思路

大道至简,用最朴素的滑动窗口三步曲即可:,移入,移出,统计。

首先分析一下题目,让算类型2使用的最少次数,即改变0/1,让它取另一个值。那么什么情况才可以呢,我们发现操作1是让头变到尾部,所以这道题可以看成一个循环数组,问你从循环数组中任意一个位置开始遍历一遍,所需要改变字符串字符的最小值。

分析完题目后我们来想一下思路:这可以当成滑动窗口做,窗口长度为字符串初始长度,循环数组的实现可以将字符串翻倍首尾相接来实现,那么如何统计当前窗口的操作数量呢?滑动窗口后,又该如何更新呢?

如果能解决这两问题,那这个题代码就很简单了。下面我阐述解决这两问题的原理,后面放代码思路。

  • 统计当前窗口操作数,我们从头分析一下,比如字符串 100110 ,下标2、3都是错的,

下标1应该与下标0一样,

下标2应该与下标0不一样,

下标3应该与下标0一样,

下标4应该与下标0不一样,

。。。。。。

显然我们可以用下标差对2取模来判断,如果与期待的结果不一样,就应该进行操作2.

  • 如何更新窗口。由于窗口问题我们一般用两个指针来维护,这里也一样,我们用左、右指针来表述吧。

右指针不用说,遍历字符串,判断是否应该用操作2.

左指针右移缩小窗口值时呢?此时我们需要分析左指针移动后是否为进行了操作2。

先给出结论:如果移动后的值进行了操作2,则操作数为 窗口长度—原操作数

如果移动后的值没进行操作2,则不变。

我们举个例子 11010 ,这个字符串先翻倍为 1111011110 ,开始时左指针指向下标0,右指针一直移到下标4,此时窗口中有3个值要取反(1、3、4处进行操作2),下面右指针右移(5处也取反,此时4个取反),左指针也右移到下标1。由于下标1处进行过操作2,所以此时之前进行操作的下标都是对的(2处应进行操作2),只需对一个值取反(5-4)

再移动也这样分析即可。

强烈建议自己举例子推一遍!

解题过程

  • 首先用k来保存s的长度,然后ant来保存窗口每次移动后的类型2操作的最少值,mi作为返回。 这三个元素是比较经典的滑动窗口三要素(自己随便取得名字),窗口长度、临时值、最终值。
  • 然后字符串翻倍,l存新的长度
  • 两个指针维护窗口,遍历字符串
  • i与j距离为奇数且值一样要进行操作2,ant++,距离为偶数值不一样,也进行操作2,ant++
  • 如果窗口过长了更新窗口,移动左指针,如果移动后的值进行了操作2,则ant=k-ant,否则不变。j++
  • 当窗口长度到了k时更新mi,最后返回mi

代码

class Solution {
public:
    int minFlips(string s) {
      int k=s.size();
      int ant=0,mi=INT_MAX;
      s+=s; int l=s.size();
      for(int i=0,j=0;i<l;i++)
      {
        if((i-j)%2&&s[i]==s[j]||((i-j)%2==0&&s[i]!=s[j]))ant++;
        while(i-j+1>k)
        {
            if(s[j]==s[j+1])ant=k-ant;
            j++;
        }
        if(i>=k-1)mi=min(mi,ant);
      }
      return mi;
    }
};

  • 26
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值