您的位置:首页 > 其它

【LeetCode】palindrome-partitioning i&ii

2017-05-02 14:26 447 查看

题干

palindrome-partitioning i

Given a string s, partition s such that every substring of the partition is a palindrome.

Return all possible palindrome partitioning of s.

For example, given s =”aab”,

Return

[
["aa","b"],
["a","a","b"]
]


palindrome-partitioning ii

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”,

Return1since the palindrome partitioning[“aa”,”b”]could be produced using 1 cut.

两个回文字符串的题,第一个要把字串都是回文的情况都存储下来,第二个是求得到字串都是回文需要对原字符串分割多少次。

解题思路

第一个题

对字符串进行遍历,每当找到一个回文的子串之后,继续找剩下的子串中的会问子串,利用递归直到找完整个字符串即可。动态规划也可解。

第二个题

运用动态规划的想法,主要步骤分为3步。

1.子串substr(0,i+1)的最小回文分割为dp[i],并且初始化,如果substr(0,i+1) 为回文子串,那么dp[i]=0,即不需要分割,否则为i,即分割i 次

任意大于1的i,子串substr(j,i+1),即遍历i之前所有子串,是回文子串,dp[i]=min(dp[i],dp[j-1]+1),即再分割一次。

如果子串substr(j,i+1)不是回文,dp[i]=min(dp[i],dp[j-1]+i-j+1)

上述构成写成代码即可。

参考代码

问题一:

class Solution {
public:
vector<vector<string>>res;//结果的每组子串存储
vector<string> tmp;//当前子串
bool isPalindrome (string s)//是否为回文的判断
{
if (s.size()<=0) return false;
int start=0,end=s.size()-1;
while(start<=end)
{
if(s[start]==s[end])
{
start++;
end--;
}
else return false;
}
return true;
}
void dfs(string s,int pos)//子串遍历
{
if (pos>=s.size())//递归退出条件,原字符串全部遍历之后退出递归
{
res.push_back(tmp);
return;
}

for(int i=0;i<=s.size()-pos;i++)
{
if (isPalindrome(s.substr(pos,i)))
{
tmp.push_back(s.substr(pos,i));//将回文子串存到结果中
dfs(s,pos+i);//从当前位置继续后面的遍历
tmp.pop_back();
}
}
}
vector<vector<string>> partition(string s)
{
dfs(s,0);
return res;
}
};


问题二:

class Solution {
public:
bool isPalindrome (string s)//回文判断
{
if (s.size()<=0) return false;
int start=0,end=s.size()-1;
while(start<=end)
{
if(s[start]==s[end])
{
start++;
end--;
}
else return false;
}
return true;
}
int minCut(string s)
{
int *dp=new int [s.length()];
int min;
for(int i=0;i<s.length();i++)
{
dp[i]=(isPalindrome(s.substr(0,i+1)))?0:i;//步骤1:初始化dp[i]
if (dp[i]==0)//当dp[i]为0的时候必为min,故直接下一次循环
continue;
for(int j=1;j<=i;j++)
{
if (isPalindrome(s.substr(j,i-j+1)))//步骤2
dp[i]=(dp[i]<dp[j-1]+1)?dp[i]:dp[j-1]+1;
else
dp[i]=(dp[i]<dp[j-1]+i-j+1)?dp[i]:dp[j-1]+i-j+1;//步骤3
}

}
return dp[s.length()-1];//返回dp最后的结果
}
};


方法讨论

两个题都可以用动态规划解决,字符串子串的这种问题主要用类似于深度遍历的方法,每次从当前位置向后遍历,适合用递归。

易错点

递归跳出条件

递归跳出是遍历结束之后进行跳出。

边界条件

1.回文判断的时候循环结束条件是要在前后两个指针顺序start<=end来结束,<或者=单独条件都不可以。

2.第2题中的s.substr(j,i-j+1)回文的判断对于子串长度为i-j+1。这个容易错误。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  leetcode