1653 使字符串平衡的最少删除次数(分析、动态规划)

1. 问题描述:

给你一个字符串 s ,它仅包含字符 'a' 和 'b'​​​​ 。你可以删除 s 中任意数目的字符,使得 s 平衡 。我们称 s 平衡的当不存在下标对 (i,j) 满足 i < j 且 s[i] = 'b' 同时 s[j]= 'a' 。请你返回使s平衡的最少删除次数。

示例 1:

输入:s = "aababbab"
输出:2
解释:你可以选择以下任意一种方案:
下标从 0 开始,删除第 2 和第 6 个字符("aababbab" -> "aaabbb"),
下标从 0 开始,删除第 3 和第 6 个字符("aababbab" -> "aabbbb")。

示例 2:

输入:s = "bbaaaaabb"
输出:2
解释:唯一的最优解是删除最前面两个字符。

提示:

  • 1 <= s.length <= 105
  • s[i] 要么是 'a' 要么是 'b' 。​

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/minimum-deletions-to-make-string-balanced

2. 思路分析:

① 分析题目可以知道比较容易想到的是:我们需要求解出0到当前位置p中字符a的数目与当前位置p到字符串结束位置的b的数目,两个数目相加表示的是不用删除的数目count,使用字符串总的长度减去count那么就是答案了,所以我们需要先遍历字符串,使用两个数组分别记录0到当前位置p的a的数目与p到字符串末尾的数目,最后再遍历这两个数组,将对应位置相加取得最大值max, 最后返回len(s) - max即可

② 其中①中的方法是比较容易想到的,除了上面的方法之外,在力扣的题解中发现了思路不错的两种解法,第一种解法是使用分析的方法,题解网址,感觉里面的思路还是很巧妙的,第二种思路是动态规划的解法,题解网址,其中使用到了二维的dp来解决,dp[x][0] 表示以"a" 结尾的最小修改次数,dp[x][1] 表示以"b" 结尾的最小修改次数

3. 代码如下:

class Solution:
    def minimumDeletions(self, s: str) -> int:
        n = len(s)
        a, b = [0] * (n + 1), [0] * (n + 1)
        for i in range(n):
            if s[i] == "a":
                a[i + 1] = a[i] + 1
            else:
                a[i + 1] = a[i]
            if s[n - 1 - i] == "b":
                b[n - 1 - i] = b[n - i] + 1
            else:
                b[n - 1 - i] = b[n - i]
        res = 0
        for i in range(1, n + 1):
            res = max(a[i] + b[i - 1], res)
        return n - res

分析:

class Solution:
    def minimumDeletions(self, s: str) -> int:
        count, dp = 0, 0
        for c in s:
            if c == "a":
                if count != dp:
                    dp += 1
            else:
                count += 1
        return dp

动态规划:

class Solution:
    # 动态规划思路
    def minimumDeletions(self, s: str) -> int:
        n = len(s)
        dp = [[0] * 2 for i in range(n + 1)]
        for i in range(n):
            if s[i] == "a":
                # 当前位置i之前以a结尾最少修改次数
                dp[i + 1][0] = dp[i][0]
                # 当前位置i之前以b结尾最少修改次数, 删除当前的a
                dp[i + 1][1] = dp[i][1] + 1
            else:
                # 当前位置i之前以a结尾最少修改次数, 删除b
                dp[i + 1][0] = dp[i][0] + 1
                # 不用删除取以a结尾, b结尾的最少的修改次数
                dp[i + 1][1] = min(dp[i][0], dp[i][1])
        return min(dp[n][0], dp[n][1])

 

 

 

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值