学习目标:
- 最长回文子串
leetcode原题链接
学习内容:
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
提示:
- 1 <= s.length <= 1000
- s 仅由数字和英文字母组成
第一种方法,暴力拆解
先定义好最后返回的最长回文串result和当前的字符传currentStr,然后使用双重for循环遍历传入的字符串str,判断当前的字符串是否是回文串并且此时回文串是否比之前记录的最长回文串长,同时满足两种条件时将最长的回文串更新为当前的字符串。最后返回记录的最长回文串result即可。
// 暴力拆解
function longestPalindrome(str) {
let result = "";//定义最长回文串
let currentStr = "";//定义当前的回文串
for (let i = 0; i < str.length; i++) {//i记录当前遍历字符串的开始位置,循环依次向后遍历
currentStr = "";//每次新的一轮开始时,将当前的回文串的变量清空
for (j = i; j < str.length; j++) {//每次开始循环是以当前i所在的下标位置为开始遍历字符串的起始位置,直到遍历到结束位置
currentStr += str.charAt(j);//逐个增加字符串的长度
if (isPalindrome(currentStr) && currentStr.length > result.length) {
//将当前的字符串传入isPalindrome进行回文判断,如果是回文串,则判断当前回文串长度是否大于之前记录的最长回文串的长度,如果大于之前的回文串,则把最长的回文字符串更新为当前字符串
result = currentStr;//更新回文串
}
}
}
return result;//返回最终的最长的回文串
}
function isPalindrome(s) {//判断是否为回文串
return s === s.split("").reverse().join("");
}
第二种方法,中心扩展法
先实现中心扩展函数,它会接受3个参数,即当前传入的字符串s,左指针和右指针,判断此时左指针是否小于0(小于0说明左指针的移动已经超过了字符串长度,右指针同理),右指针是否超过传入字符串的长度并且作用指针是否相等,这三个条件同时满足时让左指针继续左移1位,右指针右移1位,继续循环,直至条件无法满足,返回此时两个指针之间的长度。这个长度就是此时传入的字符串s的最长回文串长度。
之后是主函数方法,开始时让左右指针都指向0,然后遍历传入的字符串s,通过之前写的中心扩展函数不断得到一个个回文串长度并进行比较,选择最长的回文串,这里要考虑两种情况:传入的字符串是奇数还是偶数。如果字符串是奇数,则中心点是由一个点向外扩展;如果字符串是偶数,则中心点是两个点向外扩展。最终的回文串长度是奇偶这两种情况的最大值。接着,再通过中心点和最大回文串长度,求出最大回文串在原字符串的起止位置。再用字符串API切割出来即可。
参考文章https://blog.csdn.net/qq_42999949/article/details/117755299
/**
* @param {string} s
* @return {number}
*/
//中心扩展函数
function search(s, l, r) {
let left = l;
let right = r;
while (left >= 0 && right < s.length && s[left] === s[right]) {
left--;
right++;
}
return right - left - 1;
}
//本题主函数
function longestPalindrome(s) {
let left = right = 0;
for (let i = 0; i < s.length; i++) {
let len1 = search(s, i, i);
let len2 = search(s, i, i + 1);
let len = Math.max(len1, len2);
if (len > right - left) {
left = i - Math.floor((len - 1) / 2);
right = i + Math.floor((len / 2));
}
}
return s.slice(left, right + 1);
};