直达链接:LCR 094. 分割回文串 II
给定一个字符串
s
,请将s
分割成一些子串,使每个子串都是回文串。返回符合要求的 最少分割次数 。
示例 1:
输入:s = "aab" 输出:1 解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
输入:s = "a" 输出:0
示例 3:
输入:s = "ab" 输出:1
提示:
1 <= s.length <= 2000
s
仅由小写英文字母组成
解题思路:使用动态规划
-
首先使用一个二维数组
isPalindrome
来记录字符串s
的子串s[i...j]
是否是回文。这样可以快速查询任意子串是否为回文。 -
使用另一个动态规划数组
dp
,其中dp[i]
表示子串s[0...i-1]
的最小分割次数。初始化时,dp[i]
的最大值为i-1
(即每个字符都分割一次)。然后遍历字符串,对于每个位置i
,检查所有可能的j
(从 0 到 i),如果s[j...i]
是回文,那么dp[i+1]
可以更新为min(dp[i+1], dp[j] + 1)
。
java
class Solution {
public int minCut(String s) {
int n = s.length();
boolean[][] isPalindrome = new boolean[n][n];
int[] dp = new int[n];
for (int i = 0; i < n; i++) {
isPalindrome[i][i] = true;
}
for (int i = 0; i < n - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
isPalindrome[i][i + 1] = true;
}
}
for (int len = 3; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
if (s.charAt(i) == s.charAt(j) && isPalindrome[i + 1][j - 1]) {
isPalindrome[i][j] = true;
}
}
}
for (int i = 0; i < n; i++) {
if (isPalindrome[0][i]) {
dp[i] = 0;
} else {
dp[i] = i;
for (int j = 0; j < i; j++) {
if (isPalindrome[j + 1][i]) {
dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}
}
return dp[n - 1];
}
}
注释版:
java
class Solution {
public int minCut(String s) {
int n = s.length();
// isPalindrome[i][j] 表示子串 s[i...j] 是否是回文
boolean[][] isPalindrome = new boolean[n][n];
// dp[i] 表示子串 s[0...i] 的最小分割次数
int[] dp = new int[n];
// 初始化长度为1的子串,单个字符肯定是回文
for (int i = 0; i < n; i++) {
isPalindrome[i][i] = true;
}
// 初始化长度为2的子串,检查两个字符是否相同
for (int i = 0; i < n - 1; i++) {
if (s.charAt(i) == s.charAt(i + 1)) {
isPalindrome[i][i + 1] = true;
}
}
// 处理长度大于2的子串,检查首尾字符是否相同且中间子串是否为回文
for (int len = 3; len <= n; len++) {
for (int i = 0; i + len - 1 < n; i++) {
int j = i + len - 1;
if (s.charAt(i) == s.charAt(j) && isPalindrome[i + 1][j - 1]) {
isPalindrome[i][j] = true;
}
}
}
// 计算最小分割次数
for (int i = 0; i < n; i++) {
// 如果子串 s[0...i] 本身就是回文,无需分割
if (isPalindrome[0][i]) {
dp[i] = 0;
} else {
// 初始化为最大可能分割次数,即每个字符都分割一次
dp[i] = i;
// 遍历所有可能的分割点 j
for (int j = 0; j < i; j++) {
// 如果子串 s[j+1...i] 是回文,则更新 dp[i]
if (isPalindrome[j + 1][i]) {
dp[i] = Math.min(dp[i], dp[j] + 1);
}
}
}
}
// 返回整个字符串的最小分割次数
return dp[n - 1];
}
}

近日总结:
想回家......
但是还有好多事情没有定下来。
等的花儿都谢了,精神状态也比前段时间差了很多。
原本计划上周就回家了,结果一大堆资料文件要交,担心还有意外情况,无奈推到了这周,但是原本应该在上周就确定好的没确定下来,推到这周,这周直到现在还没有确定好。
无奈,于是我做出了最后的规划。
时也,命也,就这个端午回家吧,啥也不想管了,啥也没兴趣了,吃也吃不好,睡也睡不好,就这样吧。
直接把东西全带回家里算了,上周在跳蚤市场就摆了一次摊,别人光看不要,我价格都压这么低了,居然都没人要,我一开始就没想过要赚钱的啊。
然后摆了一小会儿,很热,也没人要,还不如回去打游戏,于是我就把东西搬回宿舍了。
这几天心情也很郁闷,讨厌学校的一切,讨厌学校的食物,难以下咽。
哦,对了,一起做了一个多月的项目的前端,项目结束之后一起爬了山,天天也会在群里聊一些有的没的。
结果嘞,爬了一次嵩山回来,开始展现他尖酸刻薄的一面,一开始爬山之前,他也有很多让我雷的点,但是爬山之后,雷的点越来越多,越来越神金了。
而我这个人,又非常的厌蠢,特别是那种蠢而不自知,你都一字一句的和人家解释,教给人家怎么样怎么样,结果人家直接拿这些攻击你。
只能说,放下助人环节,尊重他人命运,当然也没必要和不尊重他人的人继续交往。
于是我果断的社交降级了,三观冲突的太严重了。
6月初的时候,我大概就是在家了,然后6月10号左右,周末的时候,估摸着全家还会组织一次自驾游,爽歪歪。
但我还是想去爬山,虽然之前爬嵩山的时候跟噶了一样,发誓以后再也不爬山了,但是我觉得吧,其实吧,嗯......
但是家里人拒绝爬山顶山脚温差较大的山,很麻烦。
其实也可以去安徽逛逛的,比如亳州,曹操运兵道我还没去过,呜呜但是家里人都去过了,我唯一去过的也就一个花戏楼了。
其实去山东玩感觉也行。
算了,到时候看家里人咋说,去哪里玩。