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. 1 <= S.length <= 20000
  2. 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)))

 

posted @ 2020-02-13 21:40  琴影  阅读(191)  评论(0编辑  收藏  举报