题目:
给你一个字符串 s ,它仅包含字符 'a' 和 'b' 。
你可以删除 s 中任意数目的字符,使得 s 平衡 。我们称 s 平衡的 当不存在下标对 (i,j) 满足 i < j 且 s[i] = 'b' 同时 s[j]= 'a' 。
请你返回使 s 平衡 的 最少 删除次数。
算法:
方法一:前缀和
这他喵的,这种计算模型又笨又很合理。
遍历字符串,统计对每个位置i,i之前(包括i)的b的个数bCount,i之后的a的个数aCount, 求bCoubt + aCount的最小值
func minimumDeletions(s string) int {
count := make([]int, len(s) + 1)
for i := range s {
if s[i] == 'a' {
count[i + 1] = count[i] + 1
} else {
count[i + 1] = count[i]
}
}
n := len(s)
ans := math.MaxInt32
for i := 0; i < len(s); i ++ {
// s分割成两个子串[0 ~ i][i + 1, n - 1]
// 计算左子串包含的的b的个数bCount,和右子串包含的a的个数aCount
bCount := i - count[i]
aCount := count[n] - count[i + 1]
ans = min(ans, aCount + bCount)
}
return ans
}
func min(a, b int) int {
if a < b {
return a
}
return b
}
方法二:动态规划
dp[i]表示i位置删除最少次数是字符串平衡。
如果s[i] = b, 那么dp[i] = dp[i - 1]
如果s[i] = a, 那么我们可以删光i之前的所有b,或者删除a dp[i] = min(bCount, dp[i - 1] + 1)
func minimumDeletions(s string) int {
pre, cur := 0, 0
bCount := 0
for i := range s {
if s[i] == 'a' {
cur = min(bCount, pre + 1)
} else {
bCount ++
cur = pre
}
pre = cur
}
return cur
}
func min(a, b int) int {
if a < b {
return a
}
return b
}