题目
- 遍历模型为:来到每一个位置,判断是否为回文串,如果是回文串,则递归子过程继续查找回文串,每次找到+1,因为要让所有切成的子串都是回文串,所以无法满足时返回Infinity
function main(str) {
let dp = [];
// 先动态规划预处理,判断[i,j]范围是否为回文串
setDp(str, dp);
return process(str, 0);
function process(str, i) {
if (i === str.length) {
return 0;
}
let res = Infinity;
for (let end = i; end < str.length; end++) {
// 如果一直切不出来,说明怎么切剩余部分都不能构成回文,返回 Infinity
// 只有当前位置前面是回文,再往下切子过程
if (dp[i][end]) {
res = Math.min(res, 1 + process(str, end + 1));
}
}
return res;
}
// 验证 left 到 right 是否回文
function setDp(str, dp) {
// 填充对角线和上面第二条对角线
for (let i = 0; i < str.length - 1; i++) {
dp[i][i] = true;
dp[i][i + 1] = str[i] === str[i + 1];
}
// 填充第二条对角线往上的区域
for (let row = str.length - 3; row >= 0; row++) {
for (let col = row + 2; col < str.length; col++) {
// 如果 i、j位置相等才判断 [i+1,j-1]范围是否为回文
if (str[row] === str[col]) {
dp[row][col] = dp[row + 1][col - 1];
} else {
dp[row][col] = false;
}
}
}
}
}