Skip to content

Latest commit

 

History

History
191 lines (149 loc) · 4.5 KB

File metadata and controls

191 lines (149 loc) · 4.5 KB
comments difficulty edit_url tags
true
中等
字符串
动态规划

English Version

题目描述

如果一个二进制字符串,是以一些 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'

解法

方法一:前缀和 + 枚举

我们可以先统计字符串 $s$$0$ 的个数,记为 $tot$。定义一个答案变量 $ans$,初始时 $ans = tot$,表示将所有 $0$ 变成 $1$ 的翻转次数。

然后,我们可以枚举每个位置 $i$,将位置 $i$ 及其左边的所有 $1$ 变成 $0$,将位置 $i$ 右边的所有 $0$ 变成 $1$,计算这种情况下的翻转次数,即 $i + 1 - cur + tot - cur$,其中 $cur$ 表示位置 $i$ 及其左边的 $0$ 的个数,更新答案 $ans = \min(ans, i + 1 - cur + tot - cur)$

最后返回答案 $ans$ 即可。

时间复杂度 $O(n)$,其中 $n$ 为字符串 $s$ 的长度。空间复杂度 $O(1)$

Python3

class Solution:
    def minFlipsMonoIncr(self, s: str) -> int:
        tot = s.count("0")
        ans, cur = tot, 0
        for i, c in enumerate(s, 1):
            cur += int(c == "0")
            ans = min(ans, i - cur + tot - cur)
        return ans

Java

class Solution {
    public int minFlipsMonoIncr(String s) {
        int n = s.length();
        int tot = 0;
        for (int i = 0; i < n; ++i) {
            if (s.charAt(i) == '0') {
                ++tot;
            }
        }
        int ans = tot, cur = 0;
        for (int i = 1; i <= n; ++i) {
            if (s.charAt(i - 1) == '0') {
                ++cur;
            }
            ans = Math.min(ans, i - cur + tot - cur);
        }
        return ans;
    }
}

C++

class Solution {
public:
    int minFlipsMonoIncr(string s) {
        int tot = count(s.begin(), s.end(), '0');
        int ans = tot, cur = 0;
        for (int i = 1; i <= s.size(); ++i) {
            cur += s[i - 1] == '0';
            ans = min(ans, i - cur + tot - cur);
        }
        return ans;
    }
};

Go

func minFlipsMonoIncr(s string) int {
	tot := strings.Count(s, "0")
	ans, cur := tot, 0
	for i, c := range s {
		if c == '0' {
			cur++
		}
		ans = min(ans, i+1-cur+tot-cur)
	}
	return ans
}

TypeScript

function minFlipsMonoIncr(s: string): number {
    let tot = 0;
    for (const c of s) {
        tot += c === '0' ? 1 : 0;
    }
    let [ans, cur] = [tot, 0];
    for (let i = 1; i <= s.length; ++i) {
        cur += s[i - 1] === '0' ? 1 : 0;
        ans = Math.min(ans, i - cur + tot - cur);
    }
    return ans;
}

JavaScript

/**
 * @param {string} s
 * @return {number}
 */
var minFlipsMonoIncr = function (s) {
    let tot = 0;
    for (const c of s) {
        tot += c === '0' ? 1 : 0;
    }
    let [ans, cur] = [tot, 0];
    for (let i = 1; i <= s.length; ++i) {
        cur += s[i - 1] === '0' ? 1 : 0;
        ans = Math.min(ans, i - cur + tot - cur);
    }
    return ans;
};