目标
给你一个字符串 s ,如果可以将它分割成三个 非空 回文子字符串,那么返回 true ,否则返回 false 。
当一个字符串正着读和反着读是一模一样的,就称其为 回文字符串 。
示例 1:
输入:s = "abcbdd"
输出:true
解释:"abcbdd" = "a" + "bcb" + "dd",三个子字符串都是回文的。
示例 2:
输入:s = "bcbddxy"
输出:false
解释:s 没办法被分割成 3 个回文子字符串。
说明:
- 3 <= s.length <= 2000
- s 只包含小写英文字母。
思路
判断能否将给定字符串分割成三个非空回文子串。
核心逻辑:
- 计算所有子串是否是回文。
- 从起点
i = 0
开始,枚举所有终点j
,如果是s[i~j]
是回文,k--
接着以j + 1
为起点继续递归搜索。 - 结束条件是
i == s.length() || k < 0
,如果k == 0
返回 true。
代码
/**
* @date 2025-03-04 15:58
*/
public class CheckPartitioning1745 {
public boolean checkPartitioning(String s) {
int n = s.length();
boolean[][] isPalindrome = new boolean[n][n];
for (boolean[] row : isPalindrome) {
Arrays.fill(row, true);
}
for (int i = n - 2; i >= 0; i--) {
for (int j = i + 1; j < n; j++) {
isPalindrome[i][j] = s.charAt(i) == s.charAt(j) && isPalindrome[i + 1][j - 1];
}
}
char[][] mem = new char[n][4];
return dfs(0, 3, isPalindrome, s, mem);
}
public boolean dfs(int i, int k, boolean[][] isPalindrome, String s, char[][] mem) {
int n = s.length();
if (i == n || k < 0) {
return k == 0;
}
if (mem[i][k] != '\u0000') {
return mem[i][k] == 'T';
}
boolean res = false;
for (int j = i; j < n; j++) {
if (isPalindrome[i][j]) {
res = res || dfs(j + 1, k - 1, isPalindrome, s, mem);
}
}
mem[i][k] = res ? 'T' : 'F';
return res;
}
}