js实现最长回文子串

205 阅读1分钟

最近不是在用rust刷算法题嘛,浏览leetcode的时候,看到这有一个中等难度的最长回文子串 - 力扣,点进去看到,我之前提交的都是时间超限,就琢磨着自己把这个问题解决一下。目前已经实现js版本,后续会考虑出rust版本的。

代码

var longestPalindrome = function(s) {
    let res = '';
    let i = s.length , j = 0;
       
    while(j < s.length - i + 1 && i >= 1){
        let str = s.substr(j,i);
        if(isPalindrome(str)){
           res = res.length >= str.length ? res : str;
        }

        j += 1;

        if(j == s.length - i + 1){
            i -= 1;
            j = 0;
        }
    }

    return res;
};

function isPalindrome(str){
    let len = str.length;
    for(let i = 0, j = len-1; i <= j; i++,j--){
        if(str[i] != str[j]){
           return false;
        }
    }

    return true;
}

但是数据不是特别好看,因为我用的是很暴力的方法(这就是为什么老是时间超限了,有点菜。。。)。

image.png

思路

我的思路比较简单,对字符串进行遍历,按照长度生成一个个子字符串,比如说,测试用例为"aba",那么我应该测试的字符串有"aba","ab","ba","a","b","a",判断子字符串是否为回文字符串,如果是,比较是否为最长的,否则,继续判断。判断是否为回文字符串的思路也很简单(这里附上我看到的一篇文章js判断字符串是否是回文的三种方法),我这里写的是首尾依次比较,然后往内收缩,满足回文,就返回true,否则为false。

想看其他解决思路的小伙伴点击最长回文子串--题解

问题以及解决思路

之前代码超时的最主要的原因在于我用了双层for循环

      for(let i = s.length;i >= 1;i--){
           for(let j = 0;j < s.length + 1 - i;j++){
               let str = s.substr(j,i);
               
               if(isPalindrome(str)){
                  res = res.length >= str.length ? res : str;
               }
           }

       }

于是,我就想着优化一下这个主要的结构,用了while循环来取代for循环,判断条件由在两个for循环里,整合到了一个while里面,j的条件不满足时,说明长度为i的子字符串已经获取完毕,继而改变变量i和j的值,继续进行遍历。

      let i = s.length , j = 0;
       
       while(j < s.length - i + 1 && i >= 1){
          let str = s.substr(j,i);

          if(isPalindrome(str)){
            res = res.length >= str.length ? res : str;
          }

          j += 1;

          if(j == s.length - i + 1){
             i -= 1;
             j = 0;
          }
       }