您的位置:首页 > 其它

132 Palindrome Partitioning II [Leetcode]

2015-10-03 23:56 483 查看
题目内容:

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.

解题思路:

首先,要求某个长度的字符串的最小切割数,能够想到的就是分解成子问题。也就是,如果能够知道到某个下标为止的最少回文串个数的最小切割数,那么我们就能根据这个下标向后是否是回文来判断到当前下标为止是不是一个回文串。

那么,状态转移方程可以写为:

min_cut[index] = 0, if string[0,index] is Palindrome
从index向前的每个回文串的起始位置pos开始,min{min_cut[pos-1]}+1


为了能够很快得判断两个index之间的string是不是回文,避免重复计算,我们事先用一个二维数组存储两个index之间是不是回文串。

代码一开始是这样:

class Solution {
public:
int minCut(string s) {
int size(s.size());
if(size == 0 || size == 1)
return 0;

vector<vector<bool>> palindrome(size, vector<bool>(size, false));
vector<int> min_cut(size, INT_MAX);

min_cut[0] = 0;

for(int i = 0; i < size; ++i) {
for(int j = i; j < size; ++j) {
palindrome[i][j] = isPalindrome(i, j, s);
}
}

for(int i = 1; i < size; ++i) {
if(palindrome[0][i]) {
min_cut[i] = 0;
continue;
}
int index(i);
while(index > 0) {
if(palindrome[index][i]) {
int temp = min_cut[index-1] + 1;
min_cut[i] = temp < min_cut[i] ? temp : min_cut[i];
}
--index;
}
}
return min_cut[size-1];
}

bool isPalindrome(int start, int end, string &s) {
while(start < end) {
if(s[start] != s[end])
return false;
++start;
--end;
}
return true;
}
};


这里遍历判断了两个index之间是不是回文串,但是这样会超时。比如,输入是”aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa”这样的字符串时,会发生很多次比较。

改进的判断回文串的方法仍然基于动态规划。当我们知道了i+1和j-1之间的字符串是否是回文串时,只需要比较string[i]和string[j]是否相等,就能够判断i到j之间的字符串是不是回文串。但是,怎样确保isPalindrome[i][j]的求解一定在isPalindrome[i+1][j-1]之后呢?

答案是改变遍历字符串的方式。以某个index为终点,向前遍历,直到遇到字符串的起始位置,这样就能够确保isPalindrome[i][j]的求解一定在isPalindrome[i+1][j-1]之后。而isPalindrome[i][i]一定为true。

代码修改后如下:

class Solution {
public:
int minCut(string s) {
int size(s.size());
if(size == 0 || size == 1)
return 0;

vector<vector<bool>> palindrome(size, vector<bool>(size, false));
vector<int> min_cut(size, INT_MAX);

min_cut[0] = 0;
for(int i = 0; i < size; ++i)
palindrome[i][i] = true;

for(int j = 1; j < size; ++j) {
for(int i = j - 1; i >= 0; --i) {
if(i + 2 <= j)
palindrome[i][j] = ( palindrome[i+1][j-1] && s[i] == s[j] );
else
palindrome[i][j] = isPalindrome(i, j, s);
}
}

for(int i = 1; i < size; ++i) {
if(palindrome[0][i]) {
min_cut[i] = 0;
continue;
}
int index(i);
while(index > 0) {
if(palindrome[index][i]) {
int temp = min_cut[index-1] + 1;
min_cut[i] = temp < min_cut[i] ? temp : min_cut[i];
}
--index;
}
}
return min_cut[size-1];
}

bool isPalindrome(int start, int end, string &s) {
while(start < end) {
if(s[start] != s[end])
return false;
++start;
--end;
}
return true;
}
};


能够AC,但是时间很慢,160ms。还需要考虑进一步的改进方法。明日更新。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: