题目:
给定一个字符串,将字符串分成多个部分,满足每一部分都是回文串,请输出所有可能的情况。
深搜即可。
import java.util.*;
public class Solution {
public ArrayList<ArrayList<String>> partition(String s) {
ArrayList<ArrayList<String>> array=new ArrayList();
if(s == null||s.length() == 0){
return array;
}
ArrayList<String> list=new ArrayList();
dfs(s,list,array);
return array;
}
public void dfs(String s,ArrayList<String> list,ArrayList<ArrayList<String>> array){
if(s.equals("")){
array.add(new ArrayList(list));
return;
}
for(int i=1;i<=s.length();i++){
if(is_palindrome(s.substring(0,i))){
list.add(s.substring(0,i));
dfs(s.substring(i),list,array);
list.remove(list.size()-1);
}
}
}
public boolean is_palindrome(String s){
if(s.length() < 2){
return true;
}
int left=0;
int right=s.length()-1;
while(left < right){
if(s.charAt(left)!=s.charAt(right)){
return false;
}
left++;
right--;
}
return true;
}
}
1.判断子串是否为回文串;2.然后深搜遍历所有的划分。
判断子串是否为回文串采用了最朴素的循环遍历,在该题通过了测试700ms。深搜函数最重要的参数是第一个i,用来表示从字符串的i位置开始求划分,如果i已经超过了字符串的长度就说明完成了划分,保存一个可能的结果。如果i没有到字符串末尾,则判断从i开始到哪些位置是回文串,保存该回文串,然后从下一个位置继续深搜。如此就可以获得所有的划分。
关于palindrome-partitioning II的深搜问题
该问题一开始的思路肯定是直接照搬问题I的方法,采用DFS去求解。如果我们按照这个思路去实现,提交的时候会发现算法超时,即使进行了一系列的调优也不行。下面是采用DFS的最原始代码:
void dfs(int i,int parts,int len,int[][] dp)
{
if(i==len)
{
if(parts<minParts)
{
minParts=parts;
}
return;
}
for(int j=i;j<len;j++)
{
if(dp[i][j]==1)
{
dfs(j+1,parts+1,len,dp);
}
}
}
代码是一个典型的深搜,符合深搜的基本框架,但是当输入字符串是“ababababababababababababcbabababababababababababa”,算法超时。实际上这个字符串还是很短的,超时说明算法复杂度太高,或者可能需要对解空间进行剪枝,这就启发我首先试试剪枝是否有效。最容易想到的剪枝策略是:如果当前的分割的个数已经大于当前最优解,则我们停止对该路径的深搜,需要的修改是对深搜的判断条件进行修改,但还是超时了,修改之后为:
void dfs(int i,int parts,int len,int[][] dp)
{
if(i==len)
{
if(parts<minParts)
{
minParts=parts;
}
return;
}
for(int j=i;j<len;j++)
{
if(dp[i][j]==1&&parts<minParts)
{
dfs(j+1,parts+1,len,dp);
}
}
}