给你一个字符串 s
,请你将 s
分割成一些子串,使每个子串都是
回文串
。返回 s
所有可能的分割方案。
示例 1:
输入:s = "aab" 输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a" 输出:[["a"]]
这道题我知道怎么判断回文串,但是加上分割的话,我就没有思路了,
所以直接看了官方给出的思路:
回溯+动态规划预处理
class Solution {
List<List<String>> ret=new ArrayList<>();
List<String> ans=new ArrayList<>();
int n;
boolean[][] f;
public List<List<String>> partition(String s) {
n=s.length();
f=new boolean[n][n];
for(int i=0;i<n;i++){
f[i][i]=true;
}
for(int i=2;i<=n;i++){
for(int j=0;j<n;j++){
int m=i+j-1;
if(m>=n){
break;
}
if(i==2){
f[j][m]=s.charAt(j)==s.charAt(m);
}else{
f[j][m]=s.charAt(j)==s.charAt(m)&&f[j+1][m-1];
}
}
}
dfs(s,0);
return ret;
}
public void dfs(String s,int start){
if(start==n){
ret.add(new ArrayList<>(ans));//这里很容易出错
return;
}
for(int i=start;i<n;i++){
if(f[start][i]){
ans.add(s.substring(start,i+1));
dfs(s,i+1);//这里一定要+1
ans.remove(ans.size()-1);
}
}
}
}
易错点:为什么是ret.add(new ArrayList<>(ans)); 为什么不是ret.add(ans)
答:如果我们只是简单地执行 ret.add(ans);
,那么 ret
中存储的实际上是对 ans
列表的引用,而不是 ans
在那一刻的副本。这意味着,如果后续递归调用修改了 ans
,那么 ret
中存储的那个“分割方案”也会发生变化,这显然不是我们想要的结果