Leetcode 132 PalindromePartitioningII(C++ Solution)
分割字符串II DP
问题描述
给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
样例
输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
输入:s = "aaabaa"
输出:1
解释:只需一次分割就可将 s 分割成 ["a","aabaa"] 这样两个回文子串。
提示
1 <= s.length <= 2000
s
仅由小写英文字母组成
思路(Algorithm)
第一次尝试——DP、DFS、穷举
考虑到131已经实现了字符串所有回文分割的方案,可以直接穷举的到最小值。
但是Timeout:性能上复杂度最坏为O( n ∗ 2 n n*2^{n} n∗2n),eg. “ababababababababababa”
第二次尝试——DP、贪心
同样使用DP得到回文串的关系矩阵,在每次在字串搜索时尽可能地得到最大的回文串。
如,“ababababababababababa”,s[0]为头,从s[n-1]开始向左搜索,可以一步得到结果为0。
反例:
“aaabaa”
期望:1 // ["a","aabaa"]
得到:3 // ["aa","aba","a"]
第三次尝试——两次DP
第二次DP:
设minCuts[j]是以s[j]结尾的最小回文分割数,存在关系式:
m
i
n
C
u
t
s
[
j
]
=
min
i
<
j
m
i
n
C
u
t
s
[
i
]
+
1
,
i
f
s
[
i
+
1
,
j
]
是
回
文
串
minCuts[j]= \min_{i<j} {minCuts[i]}+1 ,if \space s[i+1,j]是回文串
minCuts[j]=i<jminminCuts[i]+1,if s[i+1,j]是回文串
实现代码(Implement)
#include<vector>
#include<algorithm>
using namespace std;
class Solution {
private:
vector<vector<bool>> isPalindrome;
vector<int> minCuts;
int minimum;
public:
void partition(string s) {
if (s.size() == 0) return ;
int n = s.size();
isPalindrome.assign(n, vector<bool>(n, false));
for (int i = n - 1; i >= 0; i--) {
for (int j = i; j < n; j++) {
if (i == j || (i == j - 1 && s[i] == s[j]) || (s[i] == s[j] && isPalindrome[i + 1][j - 1])) {
isPalindrome[i][j] = true;
}
}
}
}
int minCut(string s) {
int n = s.size();
if (n == 0||n==1) return 0;
partition(s);
minCuts.assign(n, INT_MAX);
for (int j = 0; j < n; j++) {
if (isPalindrome[0][j]) {
minCuts[j] = 0;
continue;
}
for (int i = 1; i <= j; i++) {
if (isPalindrome[i][j]) {
minCuts[j] = min(minCuts[i-1] + 1, minCuts[j]);
}
}
}
return minCuts[n - 1];
}
};
复杂度分析
时间复杂度:O( n 2 n^2 n2)
空间复杂度:O( n 2 n^2 n2)
声明
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning-ii
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。