📌  相关文章
📜  使二进制字符串交替的最小翻转次数(1)

📅  最后修改于: 2023-12-03 15:36:25.842000             🧑  作者: Mango

使二进制字符串交替的最小翻转次数

给定一个由 0 和 1 组成的二进制字符串 s,你需要想尽一切办法将它变成一个交替字符串,即相邻字符之间的差别必须为 1,这样的字符串叫做交替字符串。每次操作可以将 s 中的一个 0 或 1 翻转。

请你返回使 s 变成交替字符串所需的最小操作次数。如果无法完成,则返回 -1。

例子:

输入: s = "110"
输出: 1
解释: 
将第二个 '1' 翻转为 '0',s 就变成了 "101"。

输入: s = “000”
输出: 0
解释: 
s 已经是交替字符串。

输入: s = “01”
输出: 0
解释: 
s 已经是交替字符串。
思路

我们可以暴力做,对每一个字符,看它是否满足需求,如果不满足就对它进行翻转操作。

具体来说,我们用一个变量记录下一位要以哪个数字为开头,比如 $0$ 或 $1$,然后遍历字符串。如果当前字符不是我们记录的数字,我们就需要进行一次翻转。

当然上述算法不是最优解,时间复杂度最差为 $O(n^2)$,但它的代码简单易懂,可以帮助我们理解问题。

更好的做法是遍历数组,判断它和前一个数是否相等,若不相等,则翻转。

代码实现
实现 1

时间复杂度 $O(n^2)$。

def min_flips(s: str) -> int:
    cnt = 0
    pre = s[0]
    if pre == "0":
        nxt = "1"
    else:
        nxt = "0"

    for i in range(1, len(s)):
        if s[i] != nxt:
            cnt += 1
        pre = nxt
        if pre == "0":
            nxt = "1"
        else:
            nxt = "0"

    return cnt if cnt < len(s) // 2 else len(s) - cnt
实现 2

时间复杂度 $O(n)$。

def min_flips(s: str) -> int:
    cnt = 0
    for i in range(1, len(s)):
        if s[i] == s[i - 1]:
            cnt += 1
    
    return min(cnt, len(s) - cnt)
总结

本题其实本身并不难,但有一些坑点需要注意。特别是我们在进行翻转时,要将之前的翻转操作考虑进去,不能违背交替字符串的定义。

最后,我们再来看看实现 2 的代码,它的时间复杂度明显比实现 1 好。这点上也提醒我们要提供算法的时间复杂度分析,尤其是当我们面对大规模数据时,算法的时间复杂度的影响是很大的。