leetcode 2026-03-07 每日一练 - 使二进制字符串字符交替的最少反转次数

leetcode 2026-03-07 每日一练 - 使二进制字符串字符交替的最少反转次数
Austoin题目描述
LeetCode 1888. 使二进制字符串字符交替的最少反转次数
给你一个二进制字符串 s,你可以按任意顺序执行以下两种操作任意次:
- 类型 1:删除字符串
s的第一个字符并把它追加到末尾。 - 类型 2:选择字符串
s中任意一个字符并将其反转('0'变'1','1'变'0')。
请返回让 s 变成交替字符串的前提下,类型 2 的最少操作次数。
我们称一个字符串是交替的,当且仅当任意相邻字符都不同。
示例 1:
- 输入:
s = "111000" - 输出:
2
示例 2:
- 输入:
s = "010" - 输出:
0
解题思路
核心观察
这题难点是“可以先做若干次轮转,再做翻转最小化”。
把字符串轮转看成在 s+s 里取一个长度为 n 的窗口:
ss := s + s- 每个长度为
n的窗口,都对应s的一种轮转结果。
对于固定窗口,要变成交替串只需要比较两种目标模式:
- 以
0开头:010101... - 以
1开头:101010...
窗口中与目标串不一致的位置数,就是需要翻转的次数。
滑动窗口做法
- 预构造长度
2n的两个目标串target0、target1。 - 先统计第一个窗口
[0, n-1]与两目标串的差异数diff0、diff1。 - 滑动窗口右移:
- 移出左侧字符,更新
diff0/diff1 - 移入右侧字符,更新
diff0/diff1
- 移出左侧字符,更新
- 每个窗口答案是
min(diff0, diff1),全局取最小。
代码实现
1 | func minFlips(s string) int { |
核心细节
s+s是关键,它把所有轮转统一成“固定长度窗口”。- 每个窗口只看两种交替目标,不需要枚举翻转方案。
diff0/diff1通过“移出 + 移入”增量维护,避免重复统计。- 代码里用了
math.Min,记得引入math包。
复杂度分析
- 时间复杂度:
O(n)- 构造目标串
O(n) - 初始化窗口
O(n) - 滑窗
O(n)
- 构造目标串
- 空间复杂度:
O(n)ss、target0、target1都是线性空间
示例分析
以 s = "111000" 为例:
- 通过轮转可得到多个候选窗口(长度都为 6)。
- 对每个窗口分别计算与
010101、101010的差异。 - 最优窗口下,最少只需翻转 2 位。
所以答案是 2。
总结
这题的标准解法是:
- 把“轮转”转成“窗口”
- 把“最少翻转”转成“与目标交替串的差异计数”
- 用滑动窗口维护差异,做到线性时间













