
题目描述
给出一个字符串 s 和一个整数 k,若这个字符串是一个「k 回文 」,则返回 true 。
如果可以通过从字符串中删去最多 k 个字符将其转换为回文,那么这个字符串就是一个「k 回文 」。
 
示例 1:
输入:s = "abcdeca", k = 2
输出:true
解释:删去字符 “b” 和 “e”。
示例 2:
输入:s = "abbababa", k = 1
输出:true
 
提示:
    1 <= s.length <= 1000 
    s 中只含有小写英文字母 
    1 <= k <= s.length 
解法
方法一:动态规划
题目要求删去最多 \(k\) 个字符,使得剩余的字符串是回文串。可以转换为求最长回文子序列的问题。
我们定义 \(f[i][j]\) 表示字符串 \(s\) 中下标范围 \([i, j]\) 内的最长回文子序列的长度。初始时 \(f[i][i] = 1\),即每个单独的字符都是一个回文子序列。
当 \(s[i] = s[j]\) 时,有 \(f[i][j] = f[i + 1][j - 1] + 2\),即去掉 \(s[i]\) 和 \(s[j]\) 后,剩余的字符串的最长回文子序列长度加 \(2\)。
当 \(s[i] \neq s[j]\) 时,有 \(f[i][j] = \max(f[i + 1][j], f[i][j - 1])\),即去掉 \(s[i]\) 或 \(s[j]\) 后,剩余的字符串的最长回文子序列长度。
然后是否存在 \(f[i][j] + k \geq n\),如果存在,说明可以通过删去 \(k\) 个字符,使得剩余的字符串是回文串。
时间复杂度 \(O(n^2)\),空间复杂度 \(O(n^2)\)。其中 \(n\) 为字符串 \(s\) 的长度。
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15  | class Solution:
    def isValidPalindrome(self, s: str, k: int) -> bool:
        n = len(s)
        f = [[0] * n for _ in range(n)]
        for i in range(n):
            f[i][i] = 1
        for i in range(n - 2, -1, -1):
            for j in range(i + 1, n):
                if s[i] == s[j]:
                    f[i][j] = f[i + 1][j - 1] + 2
                else:
                    f[i][j] = max(f[i + 1][j], f[i][j - 1])
                if f[i][j] + k >= n:
                    return True
        return False
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22  | class Solution {
    public boolean isValidPalindrome(String s, int k) {
        int n = s.length();
        int[][] f = new int[n][n];
        for (int i = 0; i < n; ++i) {
            f[i][i] = 1;
        }
        for (int i = n - 2; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                if (s.charAt(i) == s.charAt(j)) {
                    f[i][j] = f[i + 1][j - 1] + 2;
                } else {
                    f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]);
                }
                if (f[i][j] + k >= n) {
                    return true;
                }
            }
        }
        return false;
    }
}
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24  | class Solution {
public:
    bool isValidPalindrome(string s, int k) {
        int n = s.length();
        int f[n][n];
        memset(f, 0, sizeof f);
        for (int i = 0; i < n; ++i) {
            f[i][i] = 1;
        }
        for (int i = n - 2; i >= 0; --i) {
            for (int j = i + 1; j < n; ++j) {
                if (s[i] == s[j]) {
                    f[i][j] = f[i + 1][j - 1] + 2;
                } else {
                    f[i][j] = max(f[i + 1][j], f[i][j - 1]);
                }
                if (f[i][j] + k >= n) {
                    return true;
                }
            }
        }
        return false;
    }
};
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21  | func isValidPalindrome(s string, k int) bool {
    n := len(s)
    f := make([][]int, n)
    for i := range f {
        f[i] = make([]int, n)
        f[i][i] = 1
    }
    for i := n - 2; i >= 0; i-- {
        for j := i + 1; j < n; j++ {
            if s[i] == s[j] {
                f[i][j] = f[i+1][j-1] + 2
            } else {
                f[i][j] = max(f[i+1][j], f[i][j-1])
            }
            if f[i][j]+k >= n {
                return true
            }
        }
    }
    return false
}
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20  | function isValidPalindrome(s: string, k: number): boolean {
    const n = s.length;
    const f: number[][] = Array.from({ length: n }, () => Array.from({ length: n }, () => 0));
    for (let i = 0; i < n; ++i) {
        f[i][i] = 1;
    }
    for (let i = n - 2; ~i; --i) {
        for (let j = i + 1; j < n; ++j) {
            if (s[i] === s[j]) {
                f[i][j] = f[i + 1][j - 1] + 2;
            } else {
                f[i][j] = Math.max(f[i + 1][j], f[i][j - 1]);
            }
            if (f[i][j] + k >= n) {
                return true;
            }
        }
    }
    return false;
}
  | 
 
 
 1
 2
 3
 4
 5
 6
 7
 8
 9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27  | impl Solution {
    pub fn is_valid_palindrome(s: String, k: i32) -> bool {
        let s = s.as_bytes();
        let n = s.len();
        let mut f = vec![vec![0; n]; n];
        for i in 0..n {
            f[i][i] = 1;
        }
        for i in (0..n - 2).rev() {
            for j in i + 1..n {
                if s[i] == s[j] {
                    f[i][j] = f[i + 1][j - 1] + 2;
                } else {
                    f[i][j] = std::cmp::max(f[i + 1][j], f[i][j - 1]);
                }
                if f[i][j] + k >= (n as i32) {
                    return true;
                }
            }
        }
        false
    }
}
  |