LeetCode系列之——5. Longest Palindromic Substring(JavaScript)

Q:

题目链接:Longest Palindromic Substring
先看题目要求:
Given a string s, find the longest palindromic substring in s. You may assume that the maximum length of s is 1000.

Example1:

Input: “babad”

Output: “bab”

Note: “aba” is also a valid answer.

Example2:

Input: “cbbd”

Output: “bb”

  找到一个字符串中最长的回文子串,你可以假设字符串的最大长度为1000。

分析

  最直接的思路就是:写一个判断字符串是否为回文字符串的方法,然后找出字符串中所有的子串,分别执行上述方法,然后找出满足条件的最长的子串。

A:

方法一:暴力解法

  首先写一个判断字符串是否为回文字符串的方法:

var isPalindrome = function(str, start, end){
    if(str[start] !== str[end]){
        return false;
    }
    start++;
    end--;
    if(end >= start){
        return isPalindrome(str, start, end)
    }
    return true;
}

  使用两个指针分别指向目标字符串的首尾,然后使用“夹逼法”递归调用,原理比较简单,看代码一路了然。还可以使用数组API reverse函数来实现这个方法:

var isPalindrome = function(str){
    if(str.split('').reverse().join('') === str){
        return true;
    }else{
        return false;
    }
}

  这个更简单一些,接下来看longestPalindrome函数的实现:

//取出目标字符串中的所有字串(时间复杂度为O(n2)),从长到短对每个字串执行isPalindrome方法,直到找出返回值为true的
var longestPalindrome = function(s) {
    var first = 0,len = s.length;
    var result = '';
    while(len > 0){
        first = 0;
        while(first + len <= s.length){
            var substr = s.substring(first, first + len)
            if(isPalindrome(s, first, first + len - 1)){
                len = 0;
                result = substr;
                break;
            }
            first++;
        }
        len--;
    }
    return result
};

  综合两个方法,可以看到时间复杂度为O(n3)(找子串O(n2),判断是否回文O(n))。

方法二:动态规划

  关于动态规划,我觉得这位大神解释得比较明白易懂,可以看看什么是动态规划?动态规划的意义是什么?
  首先,注意到状态转移——如果s[a][b]是回文子串,那么s[a+1][b-1]也是回文子串。反过来看,如果s[a+1][b-1]是回文子串,那么只要s[a]===s[b],则s[a][b]也为回文子串。所以,由短到长,一步步找到最长的子串。

var longestPalindrome1 = function(s) {
    var dp = [];
    var max = 1;
    var max_start = 0;//记录最长回文子串的起始索引

    //初始化二维数组
    for (let i = 0; i < s.length; i++) {
        dp.push([])
    }

    for(var end = 0;end < s.length;end++){
        for(var start = 0;start < end;start++){
            if(s[start] === s[end]){
                //第一个判断是最初级的情况有aba aa这两种情况,一定是回文子串;第二个判断就是状态转移了
                if(end - start <= 2 || dp[start+1][end-1]){
                    if(end - start + 1 > max){
                        max = end - start + 1
                        max_start = start;
                    }
                    dp[start][end] = true;
                }
            }
        }
    }
    return s.substring(max_start, max_start + max);
};

  可以看到时间复杂度为O(n2)。

方法三:Manacher算法

  这是处理该问题的大神级解法,据说时间复杂度只有O(n),具体算法请看Manacher算法总结。下面直接贴代码了:

var longestPalindrome = function(s) {
    if (s.split('').reverse() === s.split('')) {
        return s;
    }
    let maxlength = 1,
        result = s[0],
        start = 0,
        end = 1,
        arr = [];
    for (let i = 0; i < s.length; i++) {
        arr.push([])
    }
    for (let i = 0; i < s.length; i++) {
        for (let j = 0; j < i; j++) {
            if (s[i] === s[j]) {
                arr[i][j] = 1;
            }
        }

    }

    return result;
};

你可能感兴趣的:(数据结构和算法)