Problem: 1750. 删除字符串两端相同字符后的最短长度1750. 删除字符串两端相同字符后的最短长度 1750. 删除字符串两端相同字符后的最短长度
思路
双指针遍历
解题过程
模拟题目描述的过程,使用指针 l, r 指向首尾两端。
如果相同就向中心移动。为了尽可能的删除多余的前缀和后缀,需要将两侧字符相等都删除。
如果不同,当前长度就是最短长度,直接返回。
实现过程
双指针初始化:l 指向字符串开头,r 指向结尾。
循环条件:当 l < r 时循环(表示还有可操作的空间)。
字符匹配:
若 s[l] == s[r]:删除这对字符(l++, r--),然后跳过所有连续的相同字符:
左侧跳过:while (s[l] == s[l - 1] && l <= r) l++(删除前缀的连续相同字符)。
右侧跳过:while (s[r] == s[r + 1] && l <= r) r--(删除后缀的连续相同字符)。
若 s[l] != s[r]:无法继续删除,直接返回剩余长度 r - l + 1。
循环结束处理:
若 r < l,说明字符串被完全删除,返回 0。
若 r == l,说明剩余一个字符,返回 1。
边界情况思考(重要)
为什么需要在删除连续相同字符的时候需要判断条件 l<=r ?
- 防止越界和无效操作:在跳过连续字符时,需确保指针未交叉(l 不超过 r)。若 l > r,继续移动指针会访问无效内存或导致逻辑错误。
- 处理剩余字符:当 l == r 时,需检查该字符是否与删除的字符相同(可能属于前缀或后缀的一部分)。
案例 1:字符串 "aaa"(全相同字符)
初始:l=0, r=2(字符 'a' 匹配)。
删除两端:l=1, r=1。
左侧跳过:s[1]=='a' 且 l<=r(1<=1),l++ → l=2(此时 l>r)。
结果:返回 0(完全删除)。
关键:l<=r 允许在 l==r 时进入循环,确保中间字符被正确处理。
案例 2:字符串 "aba"(中间字符不同)
初始:l=0, r=2(字符 'a' 匹配)。
删除两端:l=1, r=1。
左侧跳过:s[1]=='b' != s[0]=='a',不移动。
右侧跳过:s[1]=='b' != s[2]=='a',不移动。
结果:返回 1(剩余中间字符 'b')。
案例 3:字符串 "abba"(两对相同字符)
第一轮:l=0, r=3('a'=='a'),删除后 l=1, r=2。
第二轮:l=1, r=2('b'=='b'),删除后 l=2, r=1(此时 l>r)。
结果:返回 0(完全删除)。
code
python
class Solution:def minimumLength(self, s: str) -> int:n = len(s)l = 0r = n - 1while l < r:cl = s[l]cr = s[r]if s[l] == s[r]:l += 1r -= 1while s[l] == s[l-1] and l<=r:l+=1while s[r] == s[r+1] and l<=r:r-=1else:return r-l+1return 0 if r<l else 1
c++
class Solution {
public:int minimumLength(string s) {int n = s.length();int l = 0, r = n - 1;while (l < r) {char cl = s[l], cr = s[r];if (cl == cr) {l++, r--;while (s[l] == s[l - 1] && l <= r)l++;while (s[r] == s[r + 1] && l <= r)r--;} else {return r - l + 1;}}return r < l ? 0 : 1;}
};
复杂度
- 时间复杂度: O(n)
- 空间复杂度: O(1)