Palindrome partition 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"]
]
算法:dp + dfs
dp[i][j]: s.substring(i,j+1) 是否palindrome
1. i<j: 1, if( s[i]==s[j] && dp[i+1][j-1]==1) else 0
2. i>=j: 1
dfs:对于以start为开始index的substring,考虑第一个palindrome的结束位置i 来不重复的覆盖所有情况。 path的用法是常用trick
[code]
public class Solution {
public List<List<String>> partition(String s) {
list=new ArrayList<List<String>>();
if(s==null || s.length()==0)return list;
int n=s.length();
dp=new int[n][n];
for(int i=0;i<n;i++)Arrays.fill(dp[i],-1);
List<String> path=new ArrayList<String>();
partition(s,0,path);
return list;
}
int dp[][];
List<List<String>> list;
int isPalindrome(String s, int start, int end)
{
if(start>=end)dp[start][end]=1;
if(dp[start][end]==-1)
{
if(s.charAt(start)==s.charAt(end) && isPalindrome(s,start+1,end-1)==1)dp[start][end]=1;
else dp[start][end]=0;
}
return dp[start][end];
}
void partition(String s, int start, List<String>path)
{
if(start==s.length())
{
list.add(new ArrayList<String>(path));
return;
}
for(int i=start;i<s.length();i++)
{
if(isPalindrome(s,start,i)==1)
{
path.add(s.substring(start,i+1));
partition(s,i+1,path);
path.remove(path.size()-1);
}
}
}
}
/*test cases
""
a
aab
abaabaa
*/
=================================================
Palindrome partition
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.
碰到极值的问题,经常可以用dp解决。
和 I 一样,用2维dp 记录 isPalindrome, 1维dp: cut[start] 记录从start到s.length()-1的最小cut。
可以验证一下这个一维dp的必要性:
比如[0,1,2,3,4,5], [0,1]的时候会计算一遍[2,3]+[4,5], [0,2]的时候要计算一遍[3]+[4,5], [4,5]就重复计算了。
另外要注意不切分的cut是0
[code]
public class Solution {
public int minCut(String s) {
if(s==null || s.length()<2)return 0;
int n=s.length();
dp=new int[n][n];
cut=new int [n];
for(int i=0;i<n;i++)
{
Arrays.fill(dp[i],-1);
Arrays.fill(cut,-1);
}
return cut(s,0);
}
int dp[][];
int cut[];
int isPalindrome(String s, int start, int end)
{
if(dp[start][end]!=-1)return dp[start][end];
if(start>=end)dp[start][end]=1;
else dp[start][end]= s.charAt(start)==s.charAt(end) && isPalindrome(s,start+1,end-1)==1 ? 1 : 0;
return dp[start][end];
}
int cut(String s, int start)
{
if(cut[start]!=-1)return cut[start];
if(start>=s.length()-1)cut[start]=0;
if(isPalindrome(s,start,s.length()-1)==1)cut[start]=0;
else
{
int min=s.length()-start-1;
for(int i=s.length()-2;i>=start;i--)
{
if(isPalindrome(s,start,i)==1)
{
min=Math.min(min,1+cut(s,i+1));
}
}
cut[start]=min;
}
return cut[start];
}
}
/*
test cases
""
a
aabba
*/