LeetCode题解:647. 回文子串,动态规划,JavaScript,详细注释
chencl1986 opened this issue · comments
Lee Chen commented
原题链接:647. 回文子串
解题思路:
- 假设输入
aabaca
,用这段代码生成子串:
/**
* @param {string} s
* @return {number}
*/
var countSubstrings = function (s) {
let strs = []; // 用于生成所有子串
for (let j = 0; j < s.length; j++) {
strs.push(new Array(s.length).fill(new Array(s.length).fill(' ').join('')));
for (let i = 0; i <= j; i++) {
// 生成子串的代码
strs[i][j] = s.slice(i, j + 1);
while (strs[i][j].length < s.length) {
strs[i][j] += ' ';
}
}
// 打印每次循环生成的结果
console.log(strs);
}
// 打印标记好的子串结果
console.log(strs);
};
- 可以看到最终打印的结果如下:
如果查看每一层循环结束时,打印生成的子串,会发现实际上是从左到右按列生成的。
[
[ 'a ', 'aa ', 'aab ', 'aaba ', 'aabac ', 'aabaca' ],
[ ' ', 'a ', 'ab ', 'aba ', 'abac ', 'abaca ' ],
[ ' ', ' ', 'b ', 'ba ', 'bac ', 'baca ' ],
[ ' ', ' ', ' ', 'a ', 'ac ', 'aca ' ],
[ ' ', ' ', ' ', ' ', 'c ', 'ca ' ],
[ ' ', ' ', ' ', ' ', ' ', 'a ' ]
]
-
如果将
strs
用dp
数组代替,dp[i][j]
用于标记当前子串是否回文子串,有3种可能情况:i === j
,只有一个字母,必然为回文子串。j - i === 1
,有两个字母,当s[i] === s[j]
时,即两个字母相等时,是回文子串。j - i > 1
,有两个以上字母时,先判断s[i] === s[j]
,也就是子串的首尾两个字母相等。同时如果dp[i + 1][j - 1]
,即矩阵左下方,也就是对应去除首尾字母后的子串,也是回文子串。那么当前字符串一定是回文子串。
/**
* @param {string} s
* @return {number}
*/
var countSubstrings = function (s) {
let count = 0; // 统计所有回文子串数量
let dp = []; // 将所有生成的子串用矩阵标记,是回文子串的标记为true,其余为false
// 标记每行的子串
for (let j = 0; j < s.length; j++) {
// 默认一行中所有的子串都是false
dp.push(new Array(s.length).fill(false));
// 标记每列的子串,
for (let i = 0; i <= j; i++) {
// 两个索引相等时,子串只有一个字母,此时必然是是回文串
if (j === i) {
count++; // 将子串计数
dp[i][j] = true; // 在矩阵中标记回文子串
}
// 有两个字母,且两个字母相等,是回文串
else if (j - i === 1 && s[i] === s[j]) {
count++; // 将子串计数
dp[i][j] = true; // 在矩阵中标记回文子串
} else if (
// 字符串数量多于两个
j - i > 1 &&
// 首尾两个字母相等
s[i] === s[j] &&
// 且dp[i + 1][j - 1],也就是剔除首尾后的子串是回文子串
dp[i + 1][j - 1]
) {
count++; // 将子串计数
dp[i][j] = true; // 在矩阵中标记回文子串
}
}
}
return count;
};