给你一个字符串 ``s,请你将 s
分割成一些子串,使每个子串都是回文。
返回符合要求的 最少分割次数 。
示例 1:
输入:s = "aab"
输出:1
解释:只需一次分割就可将 s 分割成 ["aa","b"] 这样两个回文子串。
示例 2:
输入:s = "a"
输出:0
示例 3:
输入:s = "ab"
输出:1
提示:
1 <= s.length <= 2000
s
仅由小写英文字母组成
解答
按照上一题的递归+回溯思路,但会卡超时:
class Solution {
private:
int cur_len;
int min_len;
public:
int minCut(string s) {
if(s.size() < 2)
return 0;
cur_len = 0;
min_len = INT_MAX;
helper(s, 0, s.size() - 1);
return min_len - 1;
}
void helper(string& s, int start, int end){
if(start > end){
min_len = min(min_len, cur_len);
return;
}
for(int sub_len = 1; sub_len <= (end - start + 1); sub_len++){
if(check(s, start, start + sub_len - 1)){
cur_len++;
helper(s, start + sub_len, end);
cur_len--;
}
}
}
bool check(string& s, int start, int end){
if(start >= end)
return true;
while(start < end){
if(s[start] != s[end])
return false;
start++;
end--;
}
return true;
}
};
参考讨论区,动态规划,先记录下字符串任意子串s[i...j]
是否为回文串,然后再进行规划:
class Solution {
public:
int minCut(string s) {
int len = s.size();
vector<vector<bool>> isPalindrome(len, vector<bool>(len, true));
for(int i = 1; i < len; i++){
for(int j = i - 1; j >= 0; j--){
isPalindrome[j][i] = (s[i] == s[j]) && (isPalindrome[j + 1][i - 1]);
}
}
vector<int> dp(len, 2000);
for(int i = 0; i < len; i++){
if(isPalindrome[0][i])
dp[i] = 0;
else{
for(int j = 0; j < i; j++){
if(isPalindrome[j + 1][i])
dp[i] = min(dp[i], dp[j] + 1);
}
}
}
return dp[len - 1];
}
};