题目一
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”]
]
分析思路
题目给我们一个字符串要求我们输出所有的字串,每个子串都是回文串。
- str1 = str.substr(0, i);取出前面下标从0开始到i结束的子串,判断str1是否是回文穿;
- 若str1是回文穿,则有可能是一种分割情况,我们new出一个list,并把str1存入到list中,之后用str2 = str.substring(i)求出剩余的子串,即从下标i开始到整个字符串结尾的子串,然后把str2作为新的字符串,把这个新的字符串和list集合一起传入到函数中,递归调用。
- 递归结束的条件是字符串的长度为0(已经找到字符串的结尾了),这个时候整个字符串满足条件,把list添加到结果集合result中。
代码
public class Solution2 {
public ArrayList<ArrayList<String>> partition(String s) {
ArrayList<ArrayList<String>> result = new ArrayList<ArrayList<String>>();
ArrayList<String> list = new ArrayList<String>();
if(s.length() == 0 || s == null){
return result;
}
calResult(result, list, s);
return result;
}
private void calResult(ArrayList<ArrayList<String>> result, ArrayList<String> list, String s) {
//如果字符串长度为0 ,满足条件
if(s.length() == 0){
result.add(new ArrayList<String>(list));
}
int len = s.length();
for(int i=1;i<=len;i++){
String subStr = s.substring(0,i);
if(isPalindrome(subStr)){
list.add(subStr);
String remainSubStr = s.substring(i);
calResult(result, list, remainSubStr);
list.remove(list.size() - 1);
}
}
}
/**
* 判断一个串是否是回文串
*/
private boolean isPalindrome(String str){
int i = 0;
int j = str.length() - 1;
while(i < j){
if(str.charAt(i) != str.charAt(j)){
return false;
}
i++;
j--;
}
return true;
}
public static void main(String[] args) {
System.out.println(new Solution2().partition("aab"));
}
}
题目二
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.
分析
这是一个动态规划问题,首先我们定义几个变量
int n = s.length() //字符串的长度
boolean dp[][] = new boolean[n][n];//它表示如果dp[j][i] = true,表示子串sub(j,i)是一个回文串。那么要判断dp[j][i] = true的条件是:
dp[j+1][i-1] == true (表示sub(j+1,i-1)是满足回文字符串) && str[j] == str[i] 或者 i - j < 2 && str[j] == str[i] (即如果i - j == 1时,为两个字符相等,如果i - j == 0时,为同一个字符) .这两种情况我们都将dp[j][i]设置成true
状态转移方程:cut[i] = min{cut(i),cut[j-1]+1},为什么加1,因为如果等于后边这个话,说明0~i并不是一个回文穿串,至少需要切割一次。
cut[n-1]即为我们需要的最小分割数
代码
public class Solution3 {
public int minCut(String s) {
int n = s.length();
int cut[] = new int[n];//记录最小分割数
boolean dp[][] = new boolean[n][n];
for(int i=0; i<n;i++){
cut[i] = i;//设置0...i的最大划分
for(int j=0;j<=i;j++){
if(s.charAt(j)==s.charAt(i)&&(i-j<2 || dp[j+1][i-1])){//判断j...i是不是回文串
dp[j][i] = true;
if(j > 0){
cut[i] = Math.min(cut[i], cut[j-1]+1);
}else{
//dp[0][i]=true,即0...i的子串是回文串,不需要切割了
cut[i]=0;
}
}
}
}
return cut[n-1];
}
public static void main(String[] args) {
System.out.println(new Solution3().minCut("aab"));
}
}