算法刷题打卡第89天:替换子串得到平衡字符串

替换子串得到平衡字符串

难度:中等

有一个只含有 'Q', 'W', 'E', 'R' 四种字符,且长度为 n 的字符串。

假如在该字符串中,这四个字符都恰好出现 n/4 次,那么它就是一个「平衡字符串」。

给你一个这样的字符串 s,请通过「替换一个子串」的方式,使原字符串 s 变成一个「平衡字符串」。

你可以用和「待替换子串」长度相同的 任何 其他字符串来完成替换。

请返回待替换子串的最小可能长度。

如果原字符串自身就是一个平衡字符串,则返回 0

示例 1:

输入:s = "QWER"
输出:0
解释:s 已经是平衡的了。

示例 2:

输入:s = "QQWE"
输出:1
解释:我们需要把一个 'Q' 替换成 'R',这样得到的 "RQWE" (或 "QRWE") 是平衡的。

示例 3:

输入:s = "QQQW"
输出:2
解释:我们可以把前面的 "QQ" 替换成 "ER"。 

示例 4:

输入:s = "QQQQ"
输出:3
解释:我们可以替换后 3 个 'Q',使 s = "QWER"。

双指针 + 哈希表

思路:
通过题目分析,不难得出结论,我们只要确保删除某个子串后,剩余的字符串统计起来,'Q' , 'W', 'E', 'R' 出现的次数小于等于 n/4 次即可,其中 n 为字符串的长度。

我们可以使用暴力算法,穷举出所有可能的子串,并统计不包含子串中字符的个数,取子串最短的结果输出,但是时间复杂度为 O ( n ) O(n) O(n),需要进行优化。

经过对上述思路的梳理,我们可以使用头尾指针来表明一个子串的开始和结尾,用哈希表来统计字符出现的次数。

  1. 经过上述的思路,我们不难推出,需要申明一个哈希表 w o r d _ d i c t s word\_dicts word_dicts,申明两个指针 l l l r r r,起初,我们定义所有的字符串都为需要替换的子串,故 l = 0 l=0 l=0 r = n r=n r=n
  2. 首先,我们需要计算出第一个不满足要求的字符所在的位置,将其左指标 l l l 更新于此,即遍历字符串,对字符串进行统计,查询出第一个字符大于 n/4 的字符串的位置。
  3. 其次,我们要对右节点进行更新,更新步骤如下:
    1. 先对右节点进行收敛,外层循环判断:
      • 如果右节点小于左节点,则循环结束。
      • 每次都将右节点的字符进行统计,如果字符数量大于 n/4,则循环结束。
      • 每一次循环没有结束,右节点都要减一。
    2. 右节点收敛后,即可得到当前左节点在当前位置时,和右节点能出现的最优替换子串, r − l + 1 r - l + 1 rl+1 即为当前替换子串长度,我们对其进行记录,若该长度最短,则替换返回结果。
    3. 左节点进行减一,将字符统计哈希表减去当前字符数量,再次重复第三步右节点更新,计算左节点减一后的最优替换子串,对最终替换长度进行更新,直到左节点位置为 − 1 -1 1 结束循环。

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n s s s 的长度。
  • 空间复杂度: O ( c ) O(c) O(c), 其中 c c c 为 4 的长度。
class Solution:
    def balancedString(self, s: str) -> int:
        max_size, res = len(s) // 4, inf
        l, r = 0, len(s) - 1
        word_dicts = {i:0 for i in "QWER"}
        # 确定左边边界
        for i in range(len(s)):
            if word_dicts[s[i]] == max_size:
                l = i
                break
            word_dicts[s[i]] += 1
        else:
            return 0
        # 右边边界查询
        while l != -1:
            # 尝试缩小窗口
            while l < r: 
                if word_dicts[s[r]] == max_size:
                    break
                word_dicts[s[r]] += 1 
                r -= 1
            l -= 1
            word_dicts[s[l]] -= 1
            # 更新最短长度
            res = min(res, r - l)
            
        return res

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/replace-the-substring-for-balanced-string

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

夏秃然

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值