389 字
2 分钟
使二进制字符串字符交替的最少反转次数 Leetcode.1888 题解 滑动窗口

Leetcode 的题目一般偏板子,除了难到我的板子题 被板子难到太菜了 我写一下题解。

题意#

给定一个 01 串 ss,求通过:

  1. 将当前第一项放到末尾。
  2. 反转一项。

两种操作让 01 串满足,其任意一项旁边项都与自己相反(010010\dots101101\dots)。求操作 2 最小次数。

题解#

满足条件的 01 串一定是 A=010A=010\dots 或者 B=101B=101\dots 中的一种,只考虑操作 2 的情况下只需要比较 ssAABB 的差异,最小差异计数就是答案。

因为操作 1 不影响最终结果,所以操作 1 实际上就是允许我们重新选择环的断点。对于偶数长度的 ss ,在哪里断都没有区别。而对于奇数长度的 ss,我们还需要考虑我们操作 2 可能先让 ss 中间出现一处 0110\dots0110\dots,再通过重新断点让其变成符合条件的 01 串。

对于不管哪种情况,我们目标 01 串是下面情况的一种:

  • 1 开头,不修改断点
  • 0 开头,不修改断点
  • 1 开头,0 结尾,修改断点
  • 0 开头,1 结尾,修改断点

因而我们可以直接通过前后缀统计差异,再枚举断点,合并为答案,最小的就是我们所求的最小次数。

代码#

class Solution {
public:
int minFlips(string s) {
int n=s.length(),ans=n;
string a="01";
for (int h=0;h<2;h++){
vector diff(s.length(),0);
int cur=0;
for (int i=0;i<n;i++){
if (s[i]!=a[h^(i&1)]) cur++;
diff[i]=cur;
}
cur=0;
int t=h^1;
for (int i=n-1;i>=0;i--){
ans=min(ans,diff[i]+cur);
if (s[i]!=a[t^((n-i-1)&1)])cur++;
}
}
return ans;
}
};
使二进制字符串字符交替的最少反转次数 Leetcode.1888 题解 滑动窗口
https://zrn.net/posts/leetcode-1888/
作者
Poi
发布于
2025-01-16
许可协议
CC BY-NC-SA 4.0