📅  最后修改于: 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)$,但它的代码简单易懂,可以帮助我们理解问题。
更好的做法是遍历数组,判断它和前一个数是否相等,若不相等,则翻转。
时间复杂度 $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
时间复杂度 $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 好。这点上也提醒我们要提供算法的时间复杂度分析,尤其是当我们面对大规模数据时,算法的时间复杂度的影响是很大的。