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

73 阅读3分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第 32 天,点击查看活动详情

问题描述

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

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

请你返回对字符串  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^5
  • s  只包含字符  '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);
};

说在后面

本人为算法业余爱好者,平时只是随着兴趣偶尔刷刷题,如果上面分享有错误的地方,欢迎指出,感激不尽。