131. 分割回文串(中等)

1,问题描述

131. 分割回文串

难度:中等

给你一个字符串 s,请你将 s 分割成一些 ,使每个子串都是 。返回 s 所有可能的分割方案。

示例 1:

1
2
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]

示例 2:

1
2
输入:s = "a"
输出:[["a"]]

提示:

  • 1 <= s.length <= 16
  • s 仅由小写英文字母组成

2,初步思考

​ 看了这种回文问题,自然就想到了动态规划的解法

3,代码处理

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
import java.util.ArrayList;
import java.util.List;

public class _131分割回文串 {

// 解法2:官方的记忆搜索感觉本质没有特别大的差别,只是处理的先后顺序变了
int[][] f;
List<List<String>> ret = new ArrayList<List<String>>();
List<String> ans = new ArrayList<String>();
int n;

public List<List<String>> partition_gov(String s) {
n = s.length();
f = new int[n][n];

dfs(s, 0);
return ret;
}

public void dfs(String s, int i) {
if (i == n) {
ret.add(new ArrayList<String>(ans));
return;
}
for (int j = i; j < n; ++j) {
if (isPalindrome(s, i, j) == 1) {
ans.add(s.substring(i, j + 1));
dfs(s, j + 1);
ans.remove(ans.size() - 1);
}
}
}

// 记忆化搜索中,f[i][j] = 0 表示未搜索,1 表示是回文串,-1 表示不是回文串
public int isPalindrome(String s, int i, int j) {
if (f[i][j] != 0) {
return f[i][j];
}
if (i >= j) {
f[i][j] = 1;
} else if (s.charAt(i) == s.charAt(j)) {
f[i][j] = isPalindrome(s, i + 1, j - 1);
} else {
f[i][j] = -1;
}
return f[i][j];
}

// 解法1:直接想到了动态规划,先把所有可能的回文整理出来
// 之后再遍历按需索取
public List<List<String>> partition_dp(String s) {
List<List<String>> res = new ArrayList<>();
char[] charArray = s.toCharArray();
boolean[][] dp = new boolean[s.length()][s.length()];
for (int i = 1; i < s.length(); i++) {
dp[i][i] = true;
dp[i - 1][i] = charArray[i] == charArray[i - 1];
}
dp[0][0] = true;

// 前行后列
for (int j = 2; j < charArray.length; j++) {// 列
for (int i = 0; i < j - 1; i++) {// 行
dp[i][j] = charArray[i] == charArray[j] && dp[i + 1][j - 1];
}
}

List<String> childRes = new ArrayList<>();
divide(res, childRes, dp, s, 0);
return res;
}

private void divide(List<List<String>> res, List<String> childPre, boolean[][] dp, String s, int start) {
if (start == s.length()) {
res.add(childPre);// 写入数据
return;
}
for (int i = start; i < s.length(); i++) {
if (dp[start][i]) {
List<String> childNew = new ArrayList<>(childPre);
childNew.add(s.substring(start, i + 1));
divide(res, childNew, dp, s, i + 1);
}
}
}

public static void main(String[] args) {
_131分割回文串 solution = new _131分割回文串();
// System.out.println(solution.partition("aab"));
System.out.println(solution.partition_dp("aabaad"));// dp[0][4]=dp[1][3]=dp[2][2]
}
}