开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第 32 天,点击查看活动详情
问题描述
给你一个只包含字符 'a','b' 和 'c' 的字符串 s ,你可以执行下面这个操作(5 个步骤)任意次:
- 选择字符串
s一个 非空 的前缀,这个前缀的所有字符都相同。 - 选择字符串
s一个 非空 的后缀,这个后缀的所有字符都相同。 - 前缀和后缀在字符串中任意位置都不能有交集。
- 前缀和后缀包含的所有字符都要相同。
- 同时删除前缀和后缀。
请你返回对字符串 s 执行上面操作任意次以后(可能 0 次),能得到的 最短长度 。
示例 1:
输入: s = "ca"
输出: 2
解释: 你没法删除任何一个字符,所以字符串长度仍然保持不变。
示例 2:
输入: s = "cabaabac"
输出: 0
解释: 最优操作序列为:
- 选择前缀 "c" 和后缀 "c" 并删除它们,得到 s = "abaaba" 。
- 选择前缀 "a" 和后缀 "a" 并删除它们,得到 s = "baab" 。
- 选择前缀 "b" 和后缀 "b" 并删除它们,得到 s = "aa" 。
- 选择前缀 "a" 和后缀 "a" 并删除它们,得到 s = "" 。
示例 3:
输入: s = "aabccabba"
输出: 3
解释: 最优操作序列为:
- 选择前缀 "aa" 和后缀 "a" 并删除它们,得到 s = "bccabb" 。
- 选择前缀 "b" 和后缀 "bb" 并删除它们,得到 s = "cca" 。
提示:
1 <= s.length <= 10^5s只包含字符'a','b'和'c'。
思路分析
首先我们要先理解一下题目意思,题目会给我们一个字符串,每次我们需要比较一下字符串的前缀和后缀,如果前缀和后缀的字母是一样的,那么我们可以删除掉该前缀和后缀,直到前缀和后缀为不同字母则结束。这里的前缀和后缀定义如下:
- 前缀:从第一个字符开始,所有与第一个字符相同的连续字符串
- 后缀:从最后一个字符开始,所有与最后一个字符相同的连续字符串
理解了题目的意思后,我们不难发现可以直接使用双指针的方法来解答这道题目:
- 1、初始化指针位置
指针应该从字符串两端向中间移动,所以我们可以初始化一个左端点指针和一个右端点指针。
let left = 0,
right = s.length - 1;
- 2、移动指针位置
每次判断左右指针位置的字符是否相同,相同则找出前缀和后缀,并移动指针模拟删除前后缀的操作。
while (left < right && s[left] == s[right]) {
const char = s[left];
while (s[left] == char) left++;
while (s[right] == char) right--;
}
- 3、计算剩余字符串长度
当左右指针位置的字符不相同,或者左指针位于右指针右边时,则说明无法继续进行删除前后缀的操作,返回左右端点区间的字符数。
return Math.max(0, right - left + 1);
AC 代码
完整代码如下:
/**
* @param {string} s
* @return {number}
*/
var minimumLength = function (s) {
let left = 0,
right = s.length - 1;
while (left < right && s[left] == s[right]) {
const char = s[left];
while (s[left] == char) left++;
while (s[right] == char) right--;
}
return Math.max(0, right - left + 1);
};
说在后面
本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。