【前端也得会算法】5. 最长回文子串 [ 中等 ]

459 阅读2分钟

Offer 驾到,掘友接招!我正在参与2022春招打卡活动,点击查看活动详情

一、题目描述:

给你一个字符串 s,找到 s 中最长的回文子串。

示例

输入: s = "babad"
输出: "bab"
解释: "aba" 同样是符合题意的答案。

示例 2:
输入: s = "cbbd"
输出: "bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

二、题解:

方法一 三循环寻找法

  • 原理。双循环截取字符串然后判断是否是回文字符串即可。
  • 思路。
    • 先声明获取回文字符串的方法getReverseStr
    • 先判断自身是否是回文字符串
    • 双循环
    • 截取字符串,判断截取字符串是否是回文且长度大于已缓存结果

代码:

var longestPalindrome = function(s) {
    const getReverseStr = (str) => {
        return str.split('').reverse().join('')
    }
    if(s === getReverseStr(s)){
        return s
    }
    let res = s[0]
    let sLen = s.length
    for(let i = 0; i < sLen; i++){
        for(let j = i+1; j < sLen; j++){
            let temp = s.substring(i,j+1)
            if(temp === getReverseStr(temp) && temp.length>res.length){
                res = temp
            }
        }
    }
    return res
};

😅结果超出时间限制了

想了下应该这种方案是判断回文字符串比较慢

优化了下判断是否是回文字符串逻辑,所以还需要一重循环判断是否是回文:

var longestPalindrome = function(s) {
    const isReverseStr = (str) => {
        let strLen = str.length
        for(let i = 0; i<strLen/2;i++){
            if(str[i] !== str[strLen-1-i]){
                return false
            }
        }
        return true
    }
    if(isReverseStr(s)){
        return s
    }
    let res = s[0]
    let sLen = s.length
    for(let i = 0; i < sLen; i++){
        for(let j = i+1; j < sLen; j++){
            let temp = s.substring(i,j+1)
            if(isReverseStr(temp) && temp.length>res.length){
                res = temp
            }
        }
    }
    return res
};

image.png

方法二 双循环记录法

  • 原理。使用双循环倒叙遍历并记录每一处是否满足回文字符即可。
  • 思路。
    • 声明长为n的数组存储是否回文
    • 双循环倒叙
    • 截取字符串判断str是否符合IP格式,否则跳过本次循环
    • 当两个小标相差小于3时,只要截取字符串开始和结束的字符相等就可以判断相等
    • 当两个小标相差大于2时,只要他前一个是否是满足回文的,就可以得知是否回文的

代码:

var longestPalindrome = function(s) {
    let n = s.length;
	let res = "";
	let booleanArr = new Array(n);
    for (let i = n - 1; i >= 0; i--) {
        for (let j = n - 1; j >= i; j--) {
            booleanArr[j] = s[i] == s[j] && (j - i < 3 || booleanArr[j - 1]);
            if (booleanArr[j] && j - i + 1 > res.length) {
                res = s.substring(i, j + 1);
            }
        }
    }
    return res;
};

image.png

方案比较

  • 三循环寻找法 时间复杂度 O(n3)。
  • 双循环记录法 时间复杂度 O(n2)。

三、总结

  • 此题可以三循环寻找法双循环记录法两种方案
  • 三循环寻找法主要是双循环截取字符串然后通过再一重循环判断是否是回文字符串即可。
  • 双循环记录法主要是使用双循环倒叙遍历并记录每一处是否满足回文字符即可。

文中如有错误,欢迎在评论区指正