一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第13天,点击查看活动详情。
前几天感冒,也没有学习。也不能全怪感冒,其实就是懒得学。。。不过,倒是把安排到五一的工作做完了
题目
给出字符串s,找出s中最长的回文字符串。
s = "babad" // 输出"bab", "aba"也同样符合;
s = "abb" // 输出"bb"
中心思想:扩散思维(利用for循环找出中心点,从中间向两边扩散。找到左右相同的最大字符串。)
题解
此题需要考虑到两种情况来找回文字符串的中心点。
1、有中心点
babaad: 此时可以以a为中心点向两边扩散找到bab,当然也可以以b为中心点找到aba;
2、无中心点
cabbad:这时字符串没有中心点,所以实际是在b与b之间找到中心点向两边扩散找到abba;
在利用for循环找中心点时需要将以上两种情况都考虑到,以保证收录到所有可能构成回文子字符串的情况。
- 代码思路
1、 如果字符串长度小于2,则直接返回该字符串;
2、定义两个变量:
start: 存储当前找到的最大回文字符串的起始位置;
maxLength: 记录当前回文字符串的长度;
start + maxLength: 回文字符串终止位置;
3、创建一个函数,判断是否同时满足以下三个条件:
① 判断左边是否出界;
② 判断右边是否出界;
③ 左边的字符是否等于右边的字符;
如果同时满足以上三个条件,则判断是否需要更i性能回文字符串的最大长度以及其实位置。
然后将left--,right++,继续做出判断直到不满足三个条件之一为止。
4、 遍历字符串寻找中心点时,每个位置都要调用两次上方的函数。第一遍检查i + 1和 i - 1,第二遍检查i和i + 1。检查两遍是为了解决上述中有无中心点的两种情况。
代码实现
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
if(s.length < 2) {
return s;
}
let start = 0;
let maxLength = 1; // 有情况为 s = "ab", 字符串不会为空
function expendAroundCenter(left, right) {
while(left >= 0 && right <= s.length && s[left] === s[right]) { // 三个边界条件判断
if (right - left +1 > maxLength){ //right - left +1 可计算数组最大长度
maxLength = right - left + 1; // 更新回文字符串的最大长度
start = left; // 更新回文字符串的起始位置
}
left--; // 向左边扩散
right++; // 向右边扩散
}
}
for(let i = 0; i<s.length;i++) { // 循环找出中心点
expendAroundCenter(i-1, i+1); // 有中心点的情况
expendAroundCenter(i, i+1); // 没有中心点的情况
}
return s.substring(start,start+maxLength)
};