删除字符串两端相同字符后的最短长度
难度:中等
给你一个只包含字符 '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,⋯,n−1],这个后缀的所有字符都相同, s [ r ] = s [ r + 1 ] = ⋯ = s [ n − 1 ] s[r] = s[r + 1] = \cdots = s[n-1] s[r]=s[r+1]=⋯=s[n−1]。
- 前缀和后缀在字符串中任意位置都不能有交集,即 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[n−1]。
- 同时删除前缀和后缀。
通过观察我们对 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 right−left+1。
需要注意的是,如果当 s s s 的长度大于 1 1 1 且 s s s 中的字符全部相等时,此时需要将 s s s 全部进行删除,则会出现 right = left − 1 \textit{right} = \textit{left} - 1 right=left−1。
复杂度分析:
- 时间复杂度: 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/