1332. 删除回文子序列

题目描述

1
给你一个字符串 s,它仅由字母 'a' 和 'b' 组成。每一次删除操作都可以从 s 中删除一个回文 子序列。
2
3
返回删除给定字符串中所有字符(字符串为空)的最小删除次数。
4
5
「子序列」定义:如果一个字符串可以通过删除原字符串某些字符而不改变原字符顺序得到,那么这个字符串就是原字符串的一个子序列。
6
7
「回文」定义:如果一个字符串向后和向前读是一致的,那么这个字符串就是一个回文。
8
9
10
11
示例 1:
12
13
输入:s = "ababa"
14
输出:1
15
解释:字符串本身就是回文序列,只需要删除一次。
16
示例 2:
17
18
输入:s = "abb"
19
输出:2
20
解释:"abb" -> "bb" -> "".
21
先删除回文子序列 "a",然后再删除 "bb"。
22
示例 3:
23
24
输入:s = "baabb"
25
输出:2
26
解释:"baabb" -> "b" -> "".
27
先删除回文子序列 "baab",然后再删除 "b"。
28
示例 4:
29
30
输入:s = ""
31
输出:0
32
33
34
提示:
35
36
0 <= s.length <= 1000
37
s 仅包含字母 'a' 和 'b'
38
在真实的面试中遇到过这道题?
Copied!

前置知识

  • 回文

公司

  • 暂无

思路

这又是一道“抖机灵”的题目,类似的题目有1297.maximum-number-of-occurrences-of-a-substring
由于只有 a 和 b 两个字符。其实最多的消除次数就是 2。这是因为每次我们可以消除一个子序列,而不是消除一个子串。这样我们就可以可以先消除全部的 1 再消除全部的 2(先消除 2 也一样),这样只需要两次即可完成。 有可能 0 次或者 1 次么?有的。
比如题目给的一次消除的情况,题目给的例子是“ababa”,我们发现其实它本身就是一个回文串,所以才可以一次全部消除。那么思路就有了:
  • 如果 s 是回文,则我们需要一次消除
  • 否则需要两次
  • 一定要注意特殊情况, 对于空字符串,我们需要 0 次
判读回文的话只需要两个指针夹逼即可,具体思路可参考125. 验证回文串

关键点解析

  • 注意审题目,一定要利用题目条件“只含有 a 和 b 两个字符”否则容易做的很麻烦

代码

代码支持:Python3、Java
Python3 Code:
1
class Solution:
2
def removePalindromeSub(self, s: str) -> int:
3
if s == '':
4
return 0
5
def isPalindrome(s):
6
l = 0
7
r = len(s) - 1
8
while l < r:
9
if s[l] != s[r]:
10
return False
11
l += 1
12
r -= 1
13
return True
14
return 1 if isPalindrome(s) else 2
Copied!
如果你觉得判断回文不是本题重点,也可以简单实现:
Python3 Code:
1
class Solution:
2
def removePalindromeSub(self, s: str) -> int:
3
if s == '':
4
return 0
5
return 1 if s == s[::-1] else 2
Copied!
Java Code:
1
class Solution {
2
public int removePalindromeSub(String s) {
3
if ("".equals(s)) {
4
return 0;
5
}
6
if (s.equals(new StringBuilder(s).reverse().toString())) {
7
return 1;
8
}
9
return 2;
10
}
11
}
Copied!
复杂度分析
  • 时间复杂度:$O(N)$
  • 空间复杂度:$O(1)$
更多题解可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。
关注公众号力扣加加,努力用清晰直白的语言还原解题思路,并且有大量图解,手把手教你识别套路,高效刷题。