1216. 验证回文串 III
大约 3 分钟
---
1216. 验证回文串 III
- 标签:字符串、动态规划
- 难度:困难
题目链接
题目大意
描述:给定一个字符串 和一个整数 。
要求:判断是否可以通过删除最多 个字符,使得剩下的字符串是回文串。
说明:
- 。
- 。
示例:
- 示例 1:
输入:s = "abcdeca", k = 2
输出:true
解释:删除 'b' 和 'e' 得到 "acdca"。- 示例 2:
输入:s = "abbababa", k = 1
输出:true解题思路
思路 1:动态规划(最长回文子序列)
1. 核心思想
删除字符使字符串变为回文串,等价于找到字符串中最长的回文子序列(LPS,Longest Palindromic Subsequence)。如果 的长度减去 LPS 的长度 ,说明可以做到。
所以问题转化为:计算字符串 的最长回文子序列的长度。
2. 阶段划分
区间 DP,按区间长度从小到大计算。
3. 定义状态
表示 (从 到 ,包含两端)中最长回文子序列的长度。
4. 状态转移方程
- 如果 :两端字符相同,它们可以同时加入回文子序列中:
- 如果 :两端字符不能同时选,取去掉一端后的较大值:
5. 初始条件
- (单个字符是长度为 的回文子序列)。
6. 最终结果
- 最长回文子序列长度 。
- 判断 。
7. 结合示例走一遍
计算 :
- : →
- : →
- ...(完整计算较复杂,这里省略中间步骤)
最终 (最长回文子序列为 )。
→ 。
思路 1:代码
class Solution:
def isValidPalindrome(self, s: str, k: int) -> bool:
n = len(s)
dp = [[0] * n for _ in range(n)]
# 初始化:单字符回文长度为 1
for i in range(n):
dp[i][i] = 1
# 区间 DP
for length in range(2, n + 1): # 区间长度
for i in range(n - length + 1):
j = i + length - 1
if s[i] == s[j]:
dp[i][j] = dp[i + 1][j - 1] + 2
else:
dp[i][j] = max(dp[i + 1][j], dp[i][j - 1])
lps = dp[0][n - 1]
return n - lps <= k思路 1:复杂度分析
- 时间复杂度:,其中 是字符串长度。区间 DP 需要两层循环。
- 空间复杂度:,需要 表。, 元素在可接受范围内。
思路 2:另一种 DP(直接求最少删除次数)
也可以直接定义 为将 变为回文串需要的最少删除次数,转移类似。最终检查 。但思路 1(LPS)更经典,理解起来也更直观。