加载中...
926-将字符串翻转到单调递增(Flip String to Monotone Increasing)
发表于:2021-12-03 | 分类: 中等
字数统计: 330 | 阅读时长: 1分钟 | 阅读量:

原文链接: https://leetcode-cn.com/problems/flip-string-to-monotone-increasing

英文原文

A binary string is monotone increasing if it consists of some number of 0's (possibly none), followed by some number of 1's (also possibly none).

You are given a binary string s. You can flip s[i] changing it from 0 to 1 or from 1 to 0.

Return the minimum number of flips to make s monotone increasing.

 

Example 1:

Input: s = "00110"
Output: 1
Explanation: We flip the last digit to get 00111.

Example 2:

Input: s = "010110"
Output: 2
Explanation: We flip to get 011111, or alternatively 000111.

Example 3:

Input: s = "00011000"
Output: 2
Explanation: We flip to get 00000000.

 

Constraints:

  • 1 <= s.length <= 105
  • s[i] is either '0' or '1'.

中文题目

如果一个由 '0''1' 组成的字符串,是以一些 '0'(可能没有 '0')后面跟着一些 '1'(也可能没有 '1')的形式组成的,那么该字符串是单调递增的。

我们给出一个由字符 '0''1' 组成的字符串 S,我们可以将任何 '0' 翻转为 '1' 或者将 '1' 翻转为 '0'

返回使 S 单调递增的最小翻转次数。

 

示例 1:

输入:"00110"
输出:1
解释:我们翻转最后一位得到 00111.

示例 2:

输入:"010110"
输出:2
解释:我们翻转得到 011111,或者是 000111。

示例 3:

输入:"00011000"
输出:2
解释:我们翻转得到 00000000。

 

提示:

  • 1 <= S.length <= 20000
  • S 中只包含字符 '0' 和 '1'

通过代码

官方题解

方法一:前缀和

思路

对于一个包含 5 个数字的字符串来说,答案可能是 '00000''00001''00011''00111''01111''11111' 中的任何一个。可以依次原始字符串转换成每个答案的代价,其中计算分成两个部分,左边全 0 的部分和右边全 1 的部分。

显然,这个问题可以简化成: 对于每种分割方法,左边有多少个 1 需要去反转,右边有多少个 0 需要去反转。

对这个问题,可以用全缀和来解决。定义 P[i+1] = A[0] + A[1] + ... + A[i]P 可以在线性时间计算出来。

假设最终答案是 x0N - x1,那么就必须反转 P[x]1(N-x) - (P[N] - P[x])0。 其中 P[N] - P[x] 是右边全 1 部分原本 1 的个数。

算法

举个例子,对于 S = "010110"P = [0, 0, 1, 1, 2, 3, 3]。假设 x=3,即最终答案左边有三个 0

P[3] = 11 在左边全 0 部分,P[6] - P[3] = 21 在右边全 1 部分。

所以,左边有 P[3] = 11 需要反转,右边有 (N-x) - (P[N] - P[x]) = 10 需要去反转。

[solution1-Java]
class Solution { public int minFlipsMonoIncr(String S) { int N = S.length(); int[] P = new int[N + 1]; for (int i = 0; i < N; ++i) P[i+1] = P[i] + (S.charAt(i) == '1' ? 1 : 0); int ans = Integer.MAX_VALUE; for (int j = 0; j <= N; ++j) { ans = Math.min(ans, P[j] + N-j-(P[N]-P[j])); } return ans; } }
[solution1-Python]
class Solution(object): def minFlipsMonoIncr(self, S): P = [0] for x in S: P.append(P[-1] + int(x)) return min(P[j] + len(S)-j-(P[-1]-P[j]) for j in xrange(len(P)))

复杂度分析

  • 时间复杂度: $O(N)$,其中 $N$ 是 S 的长度。

  • 空间复杂度: $O(N)$。

统计信息

通过次数 提交次数 AC比率
7414 13954 53.1%

提交历史

提交时间 提交结果 执行时间 内存消耗 语言
上一篇:
924-尽量减少恶意软件的传播(Minimize Malware Spread)
下一篇:
925-长按键入(Long Pressed Name)
本文目录
本文目录