926. Flip String to Monotone Increasing
题目描述
如果一个二进制字符串,是以一些 0
(可能没有 0
)后面跟着一些 1
(也可能没有 1
)的形式组成的,那么该字符串是 单调递增 的。
给你一个二进制字符串 s
,你可以将任何 0
翻转为 1
或者将 1
翻转为 0
。
返回使 s
单调递增的最小翻转次数。
示例1:
输入:s = "00110"
输出:1
解释:翻转最后一位得到 00111.
示例2:
输入:s = "010110"
输出:2
解释:翻转得到 011111,或者是 000111。
示例3:
输入:s = "00011000"
输出:2
解释:翻转得到 00000000。
提示:
1 <= s.length <= 105
s[i]
为'0'
或'1'
解决方案
方法一:前缀和
题目要求通过翻转 0
与 1
使得最后得到的二进制字符串为单调递增,
通过此可以想到:统计字符 s[i]
左边 1
数目,右边 0
的数目。将这些 1
与 0
翻转,最终的字符串 s
即可满足单调递增,翻转次数 = 左边 1
的数目 + 右边 0
的数目
因此,该问题可以采用前缀和的思路解决。
设置
sum
数组统计前缀和(长度为len(s) + 1
)sum[i]
代表字符s[i]
左边1
的数目(不包含i
)通过
sum[i]
可计算得到s[i]
右边0
的数目(包含i
)- 右边
0
的数目为:(len(s) - i) - (sum[len(s)] - sum[i])
- 右边
遍历两次字符串 s
,求得最终答案
第一次遍历:求得前缀和数组
sum
第二次遍历:计算当前翻转次数(左边
1
的数目 + 右边0
的数目)并与ans
比较,取最小值。
Python3
|
|
Java
|
|
方法二:优化前缀和
方法一种提到:
s[i]
左边1
的数目为sum[i]
s[i]
右边0
的数目为(len(s) - i) - (sum[len(s)] - sum[i])
遍历一轮
s
,二者求和的最小值即为答案
即 left_ones + right_zeros = 2 * sum[i] - i + len(s) - sum[len(s)]
因此,只需保证 2 * sum[i] - i
为最小值,然后求得所有 1
的数目,即可得到最终的翻转次数,采用常数级空间复杂度即可实现。
注意:根据之前的定义,这里 i
的最大值仍然为 len(s)
Python3
|
|
Java
|
|
Encouragement
目前就读于新加坡国立大学,转码菜鸡一枚。
决心通过日更一篇题解激励自己坚持刷题,坚持学习算法。
这是我搭建Leetcode-Everyday仓库后发布の第11篇题解,欢迎各位star并提出Issue~
点击这里,进入我的个人Leetcode主页~