leetcode
leetcode 1001 ~ 1050
验证回文串 III

验证回文串 III

难度:

标签:

题目描述

代码结果

运行时间: 116 ms, 内存: 17.9 MB



// 思路:
// 这道题的目标是验证一个字符串能否通过删除最多 k 个字符变成一个回文串。
// 我们使用动态规划来解决这个问题。
// 定义 dp[i][j] 表示字符串 s 在子串 i 到 j 范围内变成回文所需删除的最少字符数。
// 如果 s.charAt(i) == s.charAt(j),那么 dp[i][j] = dp[i+1][j-1]。
// 否则,dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1。
// 我们需要判断 dp[0][n-1] 是否 <= k,其中 n 是字符串 s 的长度。

import java.util.stream.IntStream;

public class Solution {
    public boolean isValidPalindrome(String s, int k) {
        int n = s.length();
        int[][] dp = new int[n][n];

        IntStream.range(1, n).forEach(len -> 
            IntStream.range(0, n - len).forEach(i -> {
                int j = i + len;
                if (s.charAt(i) == s.charAt(j)) {
                    dp[i][j] = dp[i + 1][j - 1];
                } else {
                    dp[i][j] = Math.min(dp[i + 1][j], dp[i][j - 1]) + 1;
                }
            })
        );

        return dp[0][n - 1] <= k;
    }
}

解释

方法:

这道题目的解法使用了动态规划的思路来处理问题。首先定义了一个二维数组dp,其中dp[i][j]表示为了使子字符串s[i:j+1]成为回文串需要删除的最小字符数。算法从字符串的后端开始遍历,通过比较字符是否相同来递推填充dp数组。如果字符相同,dp[i][j]则由dp[i+1][j-1]决定,并增加2表示两端字符相同。如果字符不同,则考虑删除左端或右端字符的情况,取两者中较大的值。过程中,如果任何dp[i][j]的值大于等于n-k(k为允许删除的最大字符数),则返回True,表示可以通过删除不超过k个字符使得s成为回文串。如果遍历完所有字符对都没有返回True,则最后返回False。

时间复杂度:

O(n^2)

空间复杂度:

O(n^2)

代码细节讲解

🦆
为什么在初始化动态规划数组`dp`时,每个`dp[i][i]`的值是设定为1而不是0?
在动态规划数组`dp`中,`dp[i][i]`代表的是子字符串s[i:i+1],即只包含单个字符的字符串。单个字符的字符串本身就是一个回文串,其不需要删除任何字符就已经是回文。因此,`dp[i][i]`的值应该设定为0,代表不需要删除任何字符。如果题解中设定为1,这可能是一个错误或者误解。正确的初始化应该是`dp[i][i] = 0`。
🦆
在递推关系中,当`s[left]`不等于`s[right]`时,为什么选择取`dp[left + 1][right]`和`dp[left][right - 1]`中的最大值而不是最小值?
在题解中,当`s[left]`不等于`s[right]`时,选择取`dp[left + 1][right]`和`dp[left][right - 1]`中的最大值是一个错误。实际上,应该选取这两者中的最小值。原因是我们希望找到使子字符串成为回文串所需的最少删除字符数。`dp[left + 1][right]`代表删除左侧字符后的最小删除数,而`dp[left][right - 1]`代表删除右侧字符后的最小删除数。取这两者的最小值能确保我们以最少的删除次数达成目标。
🦆
题解中提到,如果`dp[left][right]`的值大于等于`n - k`就返回True,请问这是如何确保删除的字符数量不超过k的?
题解中的这部分逻辑是正确的。在这个算法中,`dp[left][right]`表示的是为使子字符串`s[left:right+1]`成为回文串而需要的最少字符删除数。如果`dp[left][right]`的值大于等于`n-k`,这意味着剩余的字符数(即`n - dp[left][right]`)是大于等于`k`的。因此,我们可以确保在删除至多`k`个字符的情况下,字符串`s`可以被转换为一个回文串。
🦆
在题解算法中如何处理字符串s中可能存在的特殊字符或者空字符串输入?
题解中并没有特别提到对特殊字符或空字符串的特别处理。然而,动态规划算法本身是泛化的,能够处理任何类型的字符,包括特殊字符。对于空字符串,由于其已经是回文且不需要任何删除,算法应当直接返回True。这是因为空字符串不需要任何操作即是回文,且k的值在此情况下不影响结果。

相关问题