删除回文子序列

119 阅读3分钟

这是我参与「掘金日新计划 · 2 月更文挑战」的第 21 天,点击查看活动详情

问题描述

给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列

返回删除给定字符串中所有字符(字符串为空)的最小删除次数。

「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。

「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。

示例 1:

输入: s = "ababa"
输出: 1
解释: 字符串本身就是回文序列,只需要删除一次。

示例 2:

输入: s = "abb"
输出: 2
解释: "abb" -> "bb" -> "". 
先删除回文子序列 "a",然后再删除 "bb"

示例 3:

输入: s = "baabb"
输出: 2
解释: "baabb" -> "b" -> "". 
先删除回文子序列 "baab",然后再删除 "b"

提示:

  • 1 <= s.length <= 1000
  • s 仅包含字母 'a'  和 'b'

思路分析

首先我们先要理解一下题目意思,题目会给我们一个字符串s,字符串仅由字母 'a' 和 'b' 组成,我们可以对字符串进行删除操作,每一次删除操作都可以从 s 中删除一个回文 子序列,我们需要计算将字符串中的字符全部删除的最小删除次数。这里我们需要了解一下两个词语的定义:

  • 1、回文串

如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。如abccba,字符串逆转过来后也是abccba,所以abccba是一个回文串。

  • 2、子序列

如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。如abcdefg,我们可以删除字符串中的ceg,得到abdf,abdf即为abcdefg的一个子序列。

了解了题目的意思之后,我们也就可以开始解答题目了,因为这道题目中的字符串仅由 'a' 和 'b' 组成,所以如果我们把字符串中的b都删除掉的话,可以得到一个全由a字符组成的字符串,也就是说我们可以将字符串分成两个子序列,分别为全a和全b的字符串,而且两个子序列都为回文串,也就是说最多我们只需要进行两次操作就可以将整个字符串删除。所以我们只需要判断给定的字符串本身是否为一个回文串,如果是的话我们可以1次操作直接删除整个字符串,不是的话则需要进行2次操作。

判断回文我们可以直接循环进行判断:

const n = s.length;
for (let i = 0; i < Math.floor(n / 2); ++i) {
    if (s[i] !== s[n - 1 - i]) {
        return 2;
    }
}

当然,直接将字符串翻转过来进行比较也可以:

return s.split('').reverse().join('') == s ? 1 : 2;

完整 AC 代码如下:

AC 代码

/**
 * @param {string} s
 * @return {number}
 */
var removePalindromeSub = function(s) {
    return s.split('').reverse().join('') == s ? 1 : 2;
};

说在后面

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