题目如下:
Given a string s, partition s such that every substring of the partition is a palindrome.
Return the minimum cuts needed for a palindrome partitioning of s.
For example, given s = "aab",
Return 1 since the palindrome partitioning ["aa","b"] could be produced using 1 cut.
分析如下:
从左到右扫描s一遍,每一步都有一个子串S1, 对S1进行所有可能的切割,从所有可能的切割中找寻最小mincut并且记录在一个数组中。
以 aab为例子来看看:
第一步: 扫到S1 = a, 显然mincut = 0,
第二步, 扫到S1 = aa.
切割1: [aa] ,显然mincut = 0.
切割2: [a] + [a], 显然mincut = 1.
上面的切割方式中取最小值,mincut = 0.
第三步, 扫到S1 = aab
切割1: [aab] , 显然aab本身不是一个回文,因此不用更新mincut.
切割2: [a] + [ab] = 1+[ab] = 2;
切割3: [aa] + [b] = 1+[b] = 1;
真正在计算的时候,如何判断回文可以优化。如果采用上面一题的思路,那么每次进行回文的判断都会是O(N)的复杂度。为了优化,可以事先判断好了把信息存起来,放入一个2D数组中,这样用空间换了时间,接下来每次进行回文的判断都是O(1)的复杂度了。
我的代码:
class Solution {
private:
int** palindrome_table = NULL;
public:
void gen_table (int** &table, string &s) { //这里是int** &型,不是int**行,因为要将table分配空间后对应的新地址传回实参,不仅仅要修改table指向的内容。
table = new int*[s.length()];
for (int i = 0; i < s.length(); ++i) {
table[i] = new int[s.length()];
for (int j = 0; j < s.length(); ++j) {
table[i][j] = 0;
}
}
int left = 0, right = 0, i = 0;
//把回文判断信息放入一个2D数组中。
while (i < s.length()) {
left = i;
right = i;
//以第i个字符为中心,向两边扩展找寻形式为X,Y,Z,i,Z,Y,X的回文。
while(left>=0 && right <s.length() && s[left] == s[right]) {
table[left][right] = 1;
left--;
right++;
}
left = i;
right = i+1;
//以第i个字符和第i+1个字符为中心,向两边扩展找寻形式为X,Y,Z,i,i+1,Z,Y,X的回文。
while(left>=0 && right <s.length() && s[left] == s[right]) {
table[left][right] = 1;
left--;
right++;
}
i++;
}
return;
}
bool isPalindrome (int i, int j) {
return palindrome_table[i][j];
}
int minCut(string s) {
if (s.length() <= 1)
return 0;
gen_table(palindrome_table, s);
int* record = new int[s.length()];
for (int k = 0; k < s.length();++k)
record[k] = k;
for (int i = 1; i < s.length(); ++i) {
if (isPalindrome(0, i)) record[i] = 0;
for (int j = 1; j <= i; ++j) {
if(isPalindrome(j, i))
if(record[j - 1] + 1 < record[i] )
record[i] = record[j - 1] + 1;
//std::cout<<"i="<<i<<", j="<<j<<", substring=" <<s.substr(j, i - j + 1)<<", record[i]="<<record[i]<<", record[j]="<<record[j]<<std::endl;
}
}
int result = record[s.length() - 1];
delete record;
for (int i =0; i < s.length(); ++i) {
delete palindrome_table[i];
}
delete palindrome_table;
return result;
}
};