算法刷题打卡第97天:删除字符串两端相同字符后的最短长度

删除字符串两端相同字符后的最短长度

难度:中等

给你一个只包含字符 'a''b''c' 的字符串 s ,你可以执行下面这个操作(5 个步骤)任意次:

  • 选择字符串 s 一个 非空 的前缀,这个前缀的所有字符都相同。
  • 选择字符串 s 一个 非空 的后缀,这个后缀的所有字符都相同。
  • 前缀和后缀在字符串中任意位置都不能有交集。
  • 前缀和后缀包含的所有字符都要相同。
  • 同时删除前缀和后缀。

请你返回对字符串 s 执行上面操作任意次以后(可能 0 次),能得到的 最短长度

双指针

思路:

题目要求删除字符串 s s s 中字母相同且不相交的前缀与后缀,假设当前字符串的长度为 n n n,则执行的删除规则如下:

  • 选择字符串 s s s 一个非空的前缀 prefix = s [ 0 , ⋯   , l ] \textit{prefix} = s[0,\cdots,l] prefix=s[0,,l],这个前缀的所有字符都相同, s [ 0 ] = s [ 1 ] = ⋯ = s [ l ] s[0] = s[1] = \cdots = s[l] s[0]=s[1]==s[l]
  • 选择字符串 s s s 一个非空11的后缀 suffix = s [ r , ⋯   , n − 1 ] \textit{suffix} = s[r,\cdots,n-1] suffix=s[r,,n1],这个后缀的所有字符都相同, s [ r ] = s [ r + 1 ] = ⋯ = s [ n − 1 ] s[r] = s[r + 1] = \cdots = s[n-1] s[r]=s[r+1]==s[n1]
  • 前缀和后缀在字符串中任意位置都不能有交集,即 l < r l < r l<r
  • 前缀和后缀包含的所有字符都要相同, s [ 0 ] = s [ 1 ] = ⋯ = s [ l ] = s [ r ] = s [ r + 1 ] = ⋯ = s [ n − 1 ] s[0] = s[1] = \cdots = s[l] = s[r] = s[r + 1] = \cdots = s[n-1] s[0]=s[1]==s[l]=s[r]=s[r+1]==s[n1]
  • 同时删除前缀和后缀。

通过观察我们对 s s s 进行分类讨论如下:

  • s s s 的长度为 1 1 1 时,假设 s = “a" s = \text{``a"} s=“a",此时按照题目的删除规则此时不能删除。
  • s s s 的长度大于 1 1 1 s s s 中的所有字符均相同,假设 s = “aaaa" s = \text{``aaaa"} s=“aaaa",此时按照题目的删除规则 s s s 一定可以全部删除完。
  • s s s 的长度大于 1 1 1 s s s 存在字母相同的前缀与后缀,假设 s = “aaabbbccca" s = \text{``aaabbbccca"} s=“aaabbbccca",此时按照题目的删除规则最优选择是 s s s 应当将前缀与后缀中连续的 ‘a’ \text{`a’} ‘a’ 全部删除完,删除完成后 s ′ = “bbbccc" s' = \text{``bbbccc"} s=“bbbccc"
  • s s s 的长度大于 1 1 1 s s s 不存在字母相同的前缀与后缀,假设 s = “aaaccc" s = \text{``aaaccc"} s=“aaaccc",此时按照删除规则,无法进行删除。

根据以上的删除规则分类,我们设 left \textit{left} left right \textit{right} right 分别指向当前待删除字符串的起始位置与结束位置,然后按照规则进行删除,当前可以删除的条件必须满足如下:

  • 只有字符串的长度大于 1 1 1 时我们才进行删除,因此可以进行删除的条件一定需要满足 left < right \textit{left} < \textit{right} left<right
  • 只有存在字母相同的前缀与后缀我们才进行删除,因此可以进行删除的条件一定需要满足 s [ left ] = s [ right ] s[\textit{left}] = s[\textit{right}] s[left]=s[right]

假设有可以进行删除的前缀和后缀时,则我们将所有字母相同的前缀与后缀全部删除,此时 left \textit{left} left 需要向右移动, right \textit{right} right 需要向左移动,并删除字符串中字母相同的前缀与后缀,直到无法删除为止。最终 left \textit{left} left 指向删除后字符串的左起点, right \textit{right} right 指向删除后字符串的右终点,剩余的字符串的长度则为 right − left + 1 \textit{right} - \textit{left} + 1 rightleft+1

需要注意的是,如果当 s s s 的长度大于 1 1 1 s s s 中的字符全部相等时,此时需要将 s s s 全部进行删除,则会出现 right = left − 1 \textit{right} = \textit{left} - 1 right=left1

复杂度分析:

  • 时间复杂度: O ( n ) O(n) O(n),其中 n n n 表示字符串的长度。我们只需遍历一遍字符串即可。
  • 空间复杂度: O ( 1 ) O(1) O(1)
class Solution:
    def minimumLength(self, s: str) -> int:
        l, r = 0, len(s) - 1
        while r - l >= 1 and s[l] == s[r]:
            now = s[l]
            while l <= r and s[l] == now:
                l += 1
            while l <= r and s[r] == now:
                r -= 1
        return r - l + 1

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/minimum-length-of-string-after-deleting-similar-ends/

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

夏秃然

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

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

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

打赏作者

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

抵扣说明:

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

余额充值