分割回文串问题
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
问题分析
对字符串的切割,就相当于把所有字符拿出来,按照原本字符的次序对其进行组合,是一种特殊的组合方式,所以可以看做是回溯问题,在回溯的基础上,我们还需要进行回文判断。
所有回溯问题都可以抽象为树结构,是在一棵树上的深度优先遍历,那么在这里我们先画出一个简单的树结构,再进一分析问题。
然后进行我们回溯的三个步骤:
-
1.回溯函数的终止条件
到达树的叶子节点就是终止条件,从图中可以看出当我们切割到了字符串的末尾,就是完成了一种切割。这里我们使用一个startIndex来记录切割位置,一维数组path来保存每一种切割,二维数组result来保存总的切割方式。当startIndex>=s.size()时,就切割到末尾。
得到终止时的代码为://切割到字符串末尾,终止本次递归,保存结果 if(startIndex>=s.length()){ result.add(new ArrayList<>(path)); }
-
2.单层递归的过程
一般来说这里有三个基本步骤:
(1)for循环控制树的横向遍历
(2)递归控制纵向遍历
(3)最后进行回溯我们再来看看这个树形结构,通过for循环从左到右遍历,然后通过递归函数不断调用自己来进行纵向遍历,当遇到叶子节点时就返回;在这里使用startIndex告诉下一个切割从什么地方开始。
代码为://通过startIndex判断下次开始切割的起始位置 for(int i=startIndex;i<s.length();i++){ //判断字符串的[startIndex,i]子串是否为回文,是进行切割 if(isPalindrome(s,startIndex,i)){ String str=s.substring(startIndex,i+1 ); //获取切割的子串 path.add(str); //保存切割的子串 }else { //不是回文跳出本次循环,继续下次 continue; } backTracking(s,i+1); //递归调用,下一次切割从前一个切割的后一个元素开始 path.remove(path.size()-1); //回溯 }
-
3.确定递归函数的参数和返回值
(1)参数:通过上面的分析,确定基本需要的参数有:字符串s、startIndex(下一次切割的起始位置)
(2)返回值:void
回文判断函数
//回文判断
public boolean isPalindrome(String s,int start,int end){
//start从左到右,end从右到左,判断前后是否一致
for(int i=start,j=end;i<j;i++,j--){
if(s.charAt(i)!=s.charAt(j)){
return false;
}
}
return true;
}
整体代码
public class Partition {
List<String> path=new ArrayList<>();
List<List<String>> result=new ArrayList<>();
public List<List<String>> partition(String s) {
backTracking(s,0);
return result;
}
public void backTracking(String s,int startIndex){
//切割到字符串末尾,终止本次递归,保存结果
if(startIndex>=s.length()){
result.add(new ArrayList<>(path));
}
//通过startIndex判断下次开始切割的起始位置
for(int i=startIndex;i<s.length();i++){
//判断字符串的[startIndex,i]子串是否为回文,是进行切割
if(isPalindrome(s,startIndex,i)){
String str=s.substring(startIndex,i+1 ); //获取切割的子串,下一次切割从前一个切割的后一个元素开始
path.add(str); //保存切割的子串
}else { //不是回文跳出本次循环,继续下次
continue;
}
backTracking(s,i+1); //递归调用
path.remove(path.size()-1); //回溯
}
}
//回文判断
public boolean isPalindrome(String s,int start,int end){
//start从左到右,end从右到左,判断前后是否一致
for(int i=start,j=end;i<j;i++,j--){
if(s.charAt(i)!=s.charAt(j)){
return false;
}
}
return true;
}
}