题目
解法1:two pass
two pass,先遍历一遍得出0和1的总个数,然后遍历每个可能的位置作为切分0和1的分界线,利用前面的0和1的总个数来得出每个位置需要的flip,要注意边界条件的处理
class Solution:
def minFlipsMonoIncr(self, s: str) -> int:
n = len(s)
zero_cnt = 0
one_cnt = 0
for c in s:
if c == '0':
zero_cnt += 1
else:
one_cnt += 1
if zero_cnt == 0 or one_cnt == 0:
return 0
curr_zero_cnt = 0
curr_one_cnt = 0
# for case like:"11011"
ans = n - one_cnt
for i in range(n):
if s[i] == '0':
curr_zero_cnt += 1
else:
curr_one_cnt += 1
ans = min(ans,i+1-curr_zero_cnt + n-i-1 - (one_cnt-curr_one_cnt))
return ans
解法2:one pass dp
- one pass dp
- 在前面子问题已经解决的情况下,如果现在新来的是1,那么答案不变因为不管前面如何,在末尾加上的1都不会改变答案
- 如果新来的是0,那么两个选项,一个是把这个0变为1,另一个就是把前面所有的1都变成0
class Solution:
def minFlipsMonoIncr(self, s: str) -> int:
one_cnt = 0
flip_cnt= 0
for i in range(len(s)):
if s[i] == '1':
one_cnt += 1
else:
flip_cnt = min(flip_cnt+1,one_cnt)
return flip_cnt