132. 分割回文串 II
难度困难276收藏分享切换为英文接收动态反馈
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
go
/*
* @Description: 132
* @Version: 2.0
* @Author: kingeasternsun
* @Date: 2021-03-08 09:42:18
* @LastEditors: kingeasternsun
* @LastEditTime: 2021-03-08 11:14:20
* @FilePath: \132minCut\132.go
*/
package leetcode
/*
1. 时间换空间,计算任意两个位置是否是回文
2. 然后使用dp计算最小数量
*/
func minCut(s string) int {
if len(s) <= 1 {
return 0
}
isPaliLen := make([][]bool, len(s)) //保存以当前位置为右边节的最长回文串长度
for i := 0; i < len(s); i++ {
isPaliLen[i] = make([]bool, len(s))
}
var judgePaliFromMid = func(beg, end int, cnt int) {
for beg >= 0 && end < cnt && s[beg] == s[end] {
isPaliLen[beg][end] = true
beg--
end++
}
}
for i := 0; i < len(s); i++ {
judgePaliFromMid(i, i, len(s))
judgePaliFromMid(i, i+1, len(s))
}
//以第i个位置为结尾的子串的最小分割次数
dp := make([]int, len(s))
for end := 1; end < len(s); end++ {
dp[end] = len(s)
for beg := 0; beg <= end; beg++ {
if isPaliLen[beg][end] {
//可以直接break
if beg == 0 {
dp[end] = 0
break
}
if dp[beg-1]+1 < dp[end] {
dp[end] = dp[beg-1] + 1
}
}
}
}
return dp[len(s)-1]
}
rust
impl Solution {
pub fn min_cut(s: String) -> i32 {
if s.len() <= 1 {
return 0;
}
let mut isPali = vec![vec![false; s.len()]; s.len()];
let bs = s.into_bytes();
//预先计算任意区间是否是回文字符串
let mut judge = |mut x: usize, mut y: usize| {
while y < bs.len() && bs[x] == bs[y] {
isPali[x][y] = true;
if x == 0 {
break;
};
x -= 1;
y += 1;
}
};
(0..bs.len()).for_each(|x| {
judge(x, x);
judge(x, x + 1);
});
//dp计算
let mut dp = vec![0 as i32; bs.len()];
for end in 1..bs.len() {
dp[end] = bs.len() as i32 - 1;
for beg in 0..end + 1 {
if isPali[beg][end] {
if beg == 0 {
dp[end] = 0
} else if dp[beg - 1] + 1 < dp[end] {
dp[end] = dp[beg - 1] + 1
}
}
}
}
dp[dp.len() - 1]
}
}