LeetCode——131. 分割回文串[Palindrome Partitioning][中等]——分析及代码[Java]
一、题目
给你一个字符串 s,请你将 s 分割成一些子串,使每个子串都是 回文串 。返回 s 所有可能的分割方案。
回文串 是正着读和反着读都一样的字符串。
示例 1:
输入:s = "aab"
输出:[["a","a","b"],["aa","b"]]
示例 2:
输入:s = "a"
输出:[["a"]]
提示:
- 1 <= s.length <= 16
- s 仅由小写英文字母组成
来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/palindrome-partitioning
著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。
二、分析及代码
1. 回溯 + 动态规划
(1)思路
先对字符串进行预处理,设计一个动态规划数组 dp[i][j] 表示区间 [i,j] 是否为回文子串,计算得到所有的回文区间。
结合回溯算法,计算所有分割方法产生的字符串集合,得到分割方案。
(2)代码
class Solution {
public List<List<String>> partition(String s) {
char[] c = s.toCharArray();
int n = c.length;
boolean[][] dp = new boolean[n][n];//记录[i,j]区间是否为回文子串
for (int i = 0; i < n; i++) {
dp[i][i] = true;//奇数长度回文子串
int len = 1;
while (i - len >= 0 && i + len < n && c[i - len] == c[i + len]) {
dp[i - len][i + len] = true;
len++;
}
if (i - 1 >= 0 && c[i - 1] == c[i]) {
//偶数长度回文子串
dp[i - 1][i] = true;
len = 1;
while (i - 1 - len >= 0 && i + len < n && c[i - 1 - len] == c[i + len]) {
dp[i - 1 - len][i + len] = true;
len++;
}
}
}
List<List<String>> ans = new ArrayList<List<String>>();
List<String> str = new ArrayList<String>();
dfs(s, ans, n, dp, str, 0);
return ans;
}
public void dfs(String s, List<List<String>> ans, int n, boolean[][] dp, List<String> str, int i) {
if (i == n) {
//字符串遍历完成
ans.add(new ArrayList<String>(str));//必须复制一个 String list
return;
}
for (int j = i; j < n; j++) {
if (dp[i][j] == true) {
str.add(s.substring(i, j + 1));//添加当前回文子串
dfs(s, ans, n, dp, str, j + 1);
str.remove(str.size() - 1);//恢复原子串
}
}
}
}
(3)结果
执行用时 :9 ms,在所有 Java 提交中击败了 89.87% 的用户;
内存消耗 :52.1 MB,在所有 Java 提交中击败了 62.94% 的用户。
三、其他
暂无。