📅  最后修改于: 2023-12-03 15:27:02.498000             🧑  作者: Mango
本文将介绍如何计算清空一个二进制字符串所需的最小删除次数,以使得删除后的字符串中不含有任何连续相似字符。以字符串 "11000101101" 为例,我们需要删除两个相邻的1和两个相邻的0,得到的结果是 "10010101",不再含有连续相似字符。
我们可以从左到右扫描整个字符串,当遇到两个相邻的字符相同时,我们就将其中一个字符删除。在删除字符之后,我们需要判断删除该字符是否会使得前后两个字符变得相同。如果是,则我们需要继续删除相邻字符,直到不能再删除为止。这就是一个贪心的过程。
def min_deletion(s: str) -> int:
i, n = 0, len(s)
res = 0
while i < n-1:
if s[i] == s[i+1]:
j = i+1
while j < n and s[i] == s[j]:
j += 1
res += j-i-1
i = j-1
else:
i += 1
return res
复杂度分析:
时间复杂度:$O(n)$,其中 $n$ 是字符串的长度。
空间复杂度:$O(1)$,我们只需要常量级别的空间存储变量。
我们可以使用动态规划的方法来解决此问题,设 $dp[i][0]$ 表示将字符 $s_i$ 替换成 0 时,使得前 $i+1$ 个字符没有相邻相同字符所需要删除的字符数量,$dp[i][1]$ 表示同理,将字符 $s_i$ 替换成 1 时所需的删除字符数量。
当 $s_{i-1} = 0$ 时,我们可以选择将 $s_i$ 替换为 1,也可以选择不替换,即 $dp[i][0] = \min(dp[i-1][0], dp[i-1][1]+1)$。当 $s_{i-1} = 1$ 时同理,$dp[i][1] = \min(dp[i-1][1], dp[i-1][0]+1)$。最后的答案是 $\min(dp[n-1][0],dp[n-1][1])$。
def min_deletion(s: str) -> int:
n = len(s)
dp = [[n, n] for _ in range(n)]
dp[0][0] = s[0] == '1'
dp[0][1] = s[0] == '0'
for i in range(1, n):
if s[i] == '0':
dp[i][0] = min(dp[i-1][0], dp[i-1][1]+1)
dp[i][1] = min(dp[i-1][1]+1, dp[i-1][0]+1)
else:
dp[i][1] = min(dp[i-1][1], dp[i-1][0]+1)
dp[i][0] = min(dp[i-1][0]+1, dp[i-1][1]+1)
return min(dp[n-1][0], dp[n-1][1])
复杂度分析:
时间复杂度:$O(n)$,其中 $n$ 是字符串的长度。
空间复杂度:$O(n)$,我们需要 $dp$ 数组存储状态。