leetcode 926. Flip String to Monotone Increasing
A string of '0'
s and '1'
s is monotone increasing if it consists of some number of '0'
s (possibly 0), followed by some number of '1'
s (also possibly 0.)
We are given a string S
of '0'
s and '1'
s, and we may flip any '0'
to a '1'
or a '1'
to a '0'
.
Return the minimum number of flips to make S
monotone increasing.
Example 1:
Input: "00110"
Output: 1
Explanation: We flip the last digit to get 00111.
Example 2:
Input: "010110"
Output: 2
Explanation: We flip to get 011111, or alternatively 000111.
Example 3:
Input: "00011000"
Output: 2
Explanation: We flip to get 00000000.
Note:
1 <= S.length <= 20000
S
only consists of'0'
and'1'
characters.
题目大意:如果一个由'0'和‘1’组成的字符串,是以一些'0'(可能没有'0')后面跟着一些'1'(也可能没有'1')的形式组成的,那么该字符串是单调递增的。
给定一个由‘0’和‘1’组成的字符串S,我们可以将任何'0'翻转为'1'或者将'1'翻转为'0'。
返回使S单调递增的最小翻转次数。
题目解析:
要想把字符串变成单调递增的,只有两种可能,一种就是从某一处开始全是 1 ,之前都是 0 或者没有,另一种就是全 0 。那么我们只需要遍历1开始的位置就可以了。
对于位置 i ,我们假设从它开始后面都是 1 ,前面都是 0 ,那么需要翻转的的次数就是它以及它后面 0 的数量加上它前面 1 的数量。
如果我们用数组预处理出来 表示前i (0,..., i-1)个数1的数量。那么它后面 0 的数量就可以表示为$n - i - (dp[n] - dp[i])$,也就是后面的长度减去 1 的数量。
那么总的翻转次数就是 $dp[i] + n - i - (dp[n] - dp[i])$,我们只需要遍历所有的 i (0, ..., n - 1),找出最小值就行了。
另外还需要比较一下 $dp[n]$的大小,也就是把所有的 1 都修改为 0 。
最终时间复杂度是 ,空间复杂度也是 。
C++代码
1 class Solution { 2 public: 3 int minFlipsMonoIncr(string s) { 4 int n = s.length(); 5 vector<int> dp(n + 1, 0); 6 for (int i = 0; i < n; ++i) { 7 dp[i + 1] = dp[i] + (s[i] == '1'); 8 } 9 int res = dp[n]; 10 for (int i = 0; i < n; ++i) { 11 res = min(res, dp[i] + n - i - (dp[n] - dp[i])); 12 } 13 return res; 14 } 15 };
python3代码:
1 class Solution: 2 def minFlipsMonoIncr(self, S: str) -> int: 3 p = [0] 4 for x in S: 5 p.append(p[-1] + int(x)) 6 return min(p[i] + len(S) - i - (p[-1] - p[i]) 7 for i in range(len(p)))