dp + dfs组合
前言
动态规划,空间换时间,比如一个字符串是否为回文,看它中间部分是否为回文和两端是否相等即可。
DFS求组合,经典的回溯场景。
一、分割回文串
二、预处理DP + DFS组合
package everyday.dp;
import java.util.ArrayList;
import java.util.List;
// 分割回文串
public class Partition {
/*
target:外层目标:得到回文组合,可DFS,但是内层需要知道那个区间是回文,才能回文组合,所以 预处理是否为回文 + DFS进行组合。
*/
public List<List<String>> partition(String s) {
// 预处理各种字串是否为回文。
boolean[][] f = preProcess(s);
// dfs组合
List<List<String>> ans = new ArrayList<>();
List<String> el = new ArrayList<>();
dfs(s, 0, el, ans, f);
// 返回处理好的组合。
return ans;
}
// DFS 组合所有可能的回文串。
private void dfs(String s, int cur, List<String> el, List<List<String>> ans, boolean[][] f) {
if (cur == s.length()) {
// 合法走到终点,不仅递归结束,且将合法组合放入ans
ans.add(new ArrayList<>(el));
return;
}
// 标准回溯
for (int i = cur; i < s.length(); i++) {
if (f[cur][i]) {
el.add(s.substring(cur, i + 1));
dfs(s, i + 1, el, ans, f);
el.remove(el.size() - 1);
}
}
// 这里是没有合法的走到终点的组合。不用ans.add,并结束递归。
}
// 判定区间[i,j]是否为回文。
private boolean[][] preProcess(String s) {
int n = s.length();
boolean[][] f = new boolean[n][n];
for (int j = 0; j < n; j++) {
// 每个单独的字母都是回文。
f[j][j] = true;
for (int i = j - 1; i >= 0; i--) {
// f[i][j] 是不是回文,要看s[i] == s[j] 且f[i - 1][j - 1]是回文。
if (s.charAt(i) != s.charAt(j)) continue;
if (i + 1 == j || f[i + 1][j - 1]) f[i][j] = true;
}
}
return f;
}
public static void main(String[] args) {
new Partition().partition("aab");
}
}
总结
1)理清楚,外层需要什么,想搭起外层,又需要什么内层。自外而内的分析,自内而外的解掉子问题。
2)动态规划/DFS组合。
参考文献
[1] LeetCode 分割回文串