给你一个字符串 s,请你将 s 分割成一些 子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案
回文串:向前和向后读都是相同的字符串
输入:字符串
输出:二维字符串列表
思路:
- 切割字符串(就是组合问题)
- 判断是否回文(动态规划优化)
class Solution {
//结果列表
List<List<String>> result = new ArrayList<>();
//每个组个
List<String> list = new ArrayList<>();
public List<List<String>> partition(String s) {
//回溯
backTracking(s, 0, new StringBuilder());
return result;
}
public void backTracking(String s, int start, StringBuilder sb){
//递归终止条件
if(start == s.length()){
result.add(new ArrayList<>(list));
return;
}
//对字符串从前往后遍历
for(int i = start; i < s.length(); i++){
sb.append(s.charAt(i));
if(check(sb)){
//判断是回文,则将当前sb加入list
list.add(sb.toString());
//递归
backTracking(s, i + 1, new StringBuilder());
//回溯
list.remove(list.size() - 1);
}
}
}
//判断是否回文
public boolean check(StringBuilder sb){
for(int i = 0; i < sb.length() / 2; i++){
if(sb.charAt(i) != sb.charAt(sb.length() - 1 - i)){
return false;
}
}
return true;
}
}
使用动态规划优化
class Solution {
//结果列表
List<List<String>> result = new ArrayList<>();
//每个组个
List<String> list = new ArrayList<>();
public List<List<String>> partition(String s) {
//定义动态规划
boolean[][] dp = new boolean[s.length()][s.length()];
//从下往上遍历,从左往右遍历
for(int i = s.length() - 1; i >= 0; i--){
for(int j = i; j < s.length(); j++){
if(s.charAt(i) == s.charAt(j) && (j - i <= 1 || dp[i + 1][j - 1])){
dp[i][j] = true;
}else{
dp[i][j] = false;
}
}
}
//回溯
backTracking(s, 0, dp);
return result;
}
public void backTracking(String s, int start, boolean[][] dp){
//递归终止条件
if(start == s.length()){
result.add(new ArrayList<>(list));
return;
}
//对字符串从前往后遍历
for(int i = start; i < s.length(); i++){
if(dp[start][i]){
//判断是回文,则将当前sb加入list
list.add(s.substring(start, i + 1));
//递归
backTracking(s, i + 1, dp);
//回溯
list.remove(list.size() - 1);
}
}
}
}