LeetCode——132. 分割回文串 II[Palindrome Partitioning II][困难]——分析及代码[Java]
- 一、题目
- 二、分析及代码
-
- 1. 两次动态规划
-
- (1)思路
- (2)代码
- (3)结果
- 三、其他
一、题目
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
示例 1:
输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
输入:s = "a"
输出:0
示例 3:
输入:s = "ab"
输出:1
提示:
- 1 <= s.length <= 2000
- s 仅由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 两次动态规划
(1)思路
先对字符串进行预处理,设计一个动态规划数组 dp[i][j] 表示区间 [i,j] 是否为回文子串,计算得到所有的回文区间。
再设计一个动态规划数组 minSeg[i],表示到第 i 个元素时的最小分割次数,则 minSeg[i] 的取值为:
- 若 dp[0][i] == true,minSeg[i] = 1;
- 否则,遍历 i 左侧的区间 [j,i],对 dp[j][i] == true 的 j,minSeg[i] = min(minSeg[j - 1]) + 1。
(2)代码
class Solution {
public int minCut(String s) {
char[] c = s.toCharArray();
int n = c.length;
boolean[][] dp = new boolean[n][n];//记录[i,j]区间是否为回文串
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
dp[i][j] = false;
for (int i = 0; i < n; i++) {
int oddLen = 0, evenLen = 0;
while (i - oddLen >= 0 && i + oddLen < n && c[i - oddLen] == c[i + oddLen])//奇数长度回文串
dp[i - oddLen][i + oddLen++] = true;
if (i - 1 >= 0 && c[i - 1] == c[i]) {
while (i - 1 - evenLen >= 0 && i + evenLen < n && c[i - 1 - evenLen] == c[i + evenLen])//偶数长度回文串
dp[i - 1 - evenLen][i + evenLen++] = true;
}
}
int[] minSeg = new int[n];//到第i个元素时的最小分割次数
for (int i = 0; i < n; i++) {
minSeg[i] = i;
if (dp[0][i] == true)
minSeg[i] = 0;
else {
for (int j = 1; j <= i; j++)
if (dp[j][i] == true)
minSeg[i] = Math.min(minSeg[i], minSeg[j - 1] + 1);
}
}
return minSeg[n - 1];
}
}
(3)结果
执行用时 :11 ms,在所有 Java 提交中击败了 75.51% 的用户;
内存消耗 :38.7 MB,在所有 Java 提交中击败了 18.33% 的用户。
三、其他
暂无。