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 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.
给一个由小写字母组成的字符串s
,和一个整数k
。
按下面的要求分割字符串:
- 将
s
中的部分字符修改为其他的小写英文字母。 - 把
s
分割成k
个非空且不相交的子串,且每个子串都是回文。
返回以这种方式分割字符串所需修改的最少字符数。
这个问题和切割钢条比较相似
定义函数f(r,t)表示字符串s[0:r]
分成t
段最少需要的次数,那么
f(r, t) = min { f(i, t − 1) + check(i + 1, r) }
其中 i ∈ [0,n],而check函数用于检查将字符串s[i+1:r]所需要的最少次数。
check
函数实现也非常容易,我们可以先定义两个指针l
和r
分别指向字符串的首尾,然后将左右指针向中间靠拢,判断左右指针指向的字符是不是相同,不相同的话就需要改变一次。
和钢条切割的区别:
- check函数就可以看成切割钢条的price表.只不过price表是直接给出的,check函数需要自己实现
// 朴素递归
public int palindromePartition1(String s, int k) {
return dfs(s, s.length() - 1, k);
}
private int dfs(String s, int r, int t) {
if (t == 1) return count(s,0, r);
int res = Integer.MAX_VALUE;
for (int i = 0; i <= r; i++) {
res = Math.min(res, dfs(s, i, t - 1) + count(s, i + 1, r));
}
return res;
}
private int count(String s, int left, int right) {
int c = 0;
while (left < right) {
if (s.charAt(left++) != s.charAt(right--)) c++;
}
return c;
}
根据朴素递归,增加memo参数,即可得到带memo的记忆化递归:
// 带memo的递归
public int palindromePartition2(String s, int k) {
Integer[][] memo = new Integer[s.length() + 1][k + 1];
return dfsWithMemo(s, s.length() - 1, k, memo);
}
private int dfsWithMemo(String s, int r, int t, Integer[][] memo) {
if (t == 1) return count(s, 0, r);
if (memo[r][t] != null) return memo[r][t];
int res = Integer.MAX_VALUE;
for (int i = 0; i <= r; i++) {
res = Math.min(res, dfsWithMemo(s, i, t - 1, memo) + count(s, i + 1, r));
}
memo[r][t] = res;
return res;
}
https://coordinate.wang/index.php/archives/2791/