分割回文串 III
难度:
标签:
题目描述
You are given a string s
containing lowercase letters and an integer k
. You need to :
- First, change some characters of
s
to other lowercase English letters. - Then divide
s
intok
non-empty disjoint substrings such that each substring is a palindrome.
Return the minimal number of characters that you need to change to divide the string.
Example 1:
Input: s = "abc", k = 2 Output: 1 Explanation: You can split the string into "ab" and "c", and change 1 character in "ab" to make it palindrome.
Example 2:
Input: s = "aabbc", k = 3 Output: 0 Explanation: You can split the string into "aa", "bb" and "c", all of them are palindrome.
Example 3:
Input: s = "leetcode", k = 8 Output: 0
Constraints:
1 <= k <= s.length <= 100
.s
only contains lowercase English letters.
代码结果
运行时间: 48 ms, 内存: 16.1 MB
/*
* 思路:
* 1. 计算每个子串变成回文所需的最少修改次数。
* 2. 使用动态规划来计算将字符串分割成k个子串的最少修改次数。
* 3. 使用Java Stream简化部分代码。
*/
import java.util.stream.IntStream;
public class Solution {
public int palindromePartition(String s, int k) {
int n = s.length();
int[][] cost = new int[n][n];
// 计算每个子串变成回文的最少修改次数
IntStream.range(2, n + 1).forEach(len -> {
IntStream.range(0, n - len + 1).forEach(i -> {
int j = i + len - 1;
cost[i][j] = (s.charAt(i) == s.charAt(j)) ? cost[i + 1][j - 1] : cost[i + 1][j - 1] + 1;
});
});
// 动态规划数组,dp[i][k] 表示前 i 个字符分割成 k 个子串的最小修改次数
int[][] dp = new int[n + 1][k + 1];
IntStream.range(0, n + 1).forEach(i -> Arrays.fill(dp[i], Integer.MAX_VALUE));
dp[0][0] = 0;
// 动态规划求解
IntStream.range(1, n + 1).forEach(i -> {
IntStream.range(1, k + 1).forEach(j -> {
IntStream.range(0, i).forEach(m -> {
dp[i][j] = Math.min(dp[i][j], dp[m][j - 1] + cost[m][i - 1]);
});
});
});
return dp[n][k];
}
}
解释
方法:
该题解采用动态规划的方法来解决问题。首先预处理出任意区间[i, j]转变成回文串所需的最小修改次数,存储在二维数组ss中。接着定义状态f[i][j]表示将字符串的前j个字符分割成i个回文子串所需的最小修改次数。状态转移方程是通过枚举上一个回文子串的结尾位置l来更新,即f[i][j] = min(f[i-1][l] + ss[l][j-1]),其中l从i-1到j-1遍历。最终答案为f[k][n],即整个字符串分割成k个回文子串的最小修改次数。
时间复杂度:
O(n^3 + k*n^2)
空间复杂度:
O(n^2 + k*n)
代码细节讲解
🦆
题解中提到的二维数组ss的确切作用是什么?它如何帮助动态规划解决此问题?
▷🦆
在状态转移方程中,为什么选择遍历上一个回文子串的结尾位置l从i-1到j-1?
▷🦆
在动态规划数组f的初始化中,为什么f[0][0]初始化为0,而其他f[i][0]的值是什么?
▷