对于Palindrome Partitioning I ,题目对于时间复杂度要求不是很高(因为要求所有情况),所以直接搜索,或者先做dp获取之情两点间字符串是否回文,之后对这一步得到的二维数组进行dfs或者dp都是可以的
方法一:
public class Solution {
public List<List<String>> partition(String s) {
if(s.length()==0) return re;
dp=getDp(s);
backtrace(0,s);
return re;
}
List<List<String>> re=new ArrayList<List<String>>();
List<String> trace=new ArrayList<String>();
boolean[][] dp;
public void backtrace(int k,String s){
if(k==s.length()){
re.add(new ArrayList<String>(trace));
return;
}
for(int i=k+1;i<=s.length();i++){
String str=s.substring(k,i);
if(dp[k][i-1]){
trace.add(str);
backtrace(i,s);
trace.remove(trace.size()-1);
}
}
}
public boolean[][] getDp(String s){
char[] ss=s.toCharArray();
boolean dp[][]=new boolean[ss.length][ss.length];
for(int i=0;i<ss.length;i++){
dp[i][i]=true;
}
for(int len=1;len<ss.length;len++){
for(int i=0;i<ss.length-len;i++){
int j=i+len;
if(i+1>j-1)
dp[i][j]=ss[i]==ss[j];
else
dp[i][j]=dp[i+1][j-1]&&ss[i]==ss[j];
}
}
return dp;
}
public static void main(String[] args) {
Solution s=new Solution();
System.out.println(s.partition("aab"));
}
}
方法二(dp):
(懒得再写一遍,所以copy他人的)
public class Solution3 {
//dp 效率更高
public static List<List<String>> partition(String s) {
int len = s.length();
List<List<String>>[] result = new List[len + 1];
result[0] = new ArrayList<List<String>>();
result[0].add(new ArrayList<String>());
boolean[][] pair = new boolean[len][len];
for (int i = 0; i < s.length(); i++) {
result[i + 1] = new ArrayList<List<String>>();
for (int left = 0; left <= i; left++) {
if (s.charAt(left) == s.charAt(i) && (i-left <= 1 || pair[left + 1][i - 1])) {
pair[left][i] = true;
String str = s.substring(left, i + 1);
for (List<String> r : result[left]) {
List<String> ri = new ArrayList<String>(r);
ri.add(str);
result[i + 1].add(ri);
}
}
}
}
return result[len];
}
}
对于Palindrome Partitioning II,技巧相似,先dp,再对所得二维数组dp或者dfs:
代码:
public class Solution {
//分析:先用dp做预处理 之后的所有操作相当于做一个从s.length()-1向前的搜索
//注意:为了让决策树更简介 所以做预处理都将从前往后的搜索转换为从后向前
//对于一个从后向前的搜索 最小子问题是从前向后的 所以可以通过对map进行前往后的dp或者从后向前的dfs实现
public int minCut(String s) {
if(s.length()==0) return 0;
boolean[][] map=getDp(s);
int[] dp=new int[s.length()+1];
for(int i=0;i<s.length();i++){//这段dp代码是可以转换为对map的dfs的
dp[i+1]=i+1;
for(int j=0;j<=i;j++){
if(map[j][i]) dp[i+1]=Math.min(dp[j+1-1]+1,dp[i+1]);
}
}
return dp[dp.length-1]-1;
}
public boolean[][] getDp(String s){
boolean[][] dp=new boolean[s.length()][s.length()];
for(int len=0;len<s.length();len++){ //这里下标不要弄错
for(int i=0;i<s.length()-len;i++){
int j=i+len;
if(i==j) dp[i][j]=true;
else if(i==j-1){
dp[i][j]=s.charAt(i)==s.charAt(j);
}else{
dp[i][j]=dp[i+1][j-1]&&s.charAt(i)==s.charAt(j);
}
}
}
return dp;
}
}