leetcode - 005 最长回文子串

版权声明:本文为博主原创文章,转载请注明原文链接。 https://blog.csdn.net/crf_moonlight/article/details/82716683

题目

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

示例 1:

输入: "babad"
输出: "bab"
注意: "aba"也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

解题思路

暴力求解

大概思路是这样

let result = "";
for (let i = 0; i < s.length; i++) {
	for (let j = i; j < s.length; j++) {
		let sub = s.subStr(i, j+1);
		if (checkSubstring(sub)) {
			if (result.length < sub.length) {
				result = sub;
			}
		}
	}
}

两层循环套一个检查是否是回文串的函数,时间复杂度O(n3)

动态规划

最长的回文子串,去掉首尾肯定还是回文子串,于是可以从最短的回文子串开始一点点找到更长一点的回文子串

Array.prototype.setPush = function(val) {
    if (!this.some(x => x === val)) {
        this.push(val);
    }
}

String.prototype.searchAll = function(val) {
    let result = [];
    for (let i = 0; i < this.length;) {
        let index = this.indexOf(val, i);
        if (index === -1) break;
        else {
            result.push(index);
            i = index+1;
        }
    }
    return result;
}

var longestPalindrome = function(s) {

    if (s === "") return "";

    const length = s.length;
    let temp = [];
    // 将1长度和2长度的回文子串全部取出
    for (let i = 0; i < length; i++) {
        temp.setPush(s[i]);
        if (s[i] === s[i+1]) {
            temp.setPush(s[i]+s[i]);
        }
    }

    while (true) {
        let tempTwo = [];
        for (let i = 0; i < temp.length; i++){
            let indexes = s.searchAll(temp[i]);
            for (index of indexes) {
                let a = index-1;
                let b = index+temp[i].length;
                if (s[a] === s[b] && s[a] !== undefined) {
                    tempTwo.setPush(s.slice(a, b+1));
                }
            }
        }
        if (tempTwo.length > 0) {
            temp = tempTwo;
        }
        else {
            let maybeMaxLength = temp[0].length;
            if (temp.some(x => x.length !== maybeMaxLength)) {
                for (x of temp) {
                    if (x.length > maybeMaxLength) return x;
                }
            }
            return temp[0];
        }
    }
};

时间复杂度为O(n2),空间复杂度为O(n2)。没什么问题,但是在js中超时了,leetcode中判定超时的例子实际运行时间大概在2s左右,应该是中间某些步骤需要优化

中心扩展算法

因为回文是对称的,可以找到一个中心向左右两边扩展。考虑奇数串和偶数串两种情况,可能有n + (n - 1)个中心
直接照搬解答中的java代码并做简单修改,通过了…

function expandAroundCenter(s, left, right) {
    let L = left, R = right;
    while(L >= 0 && R < s.length && s[L] === s[R]) {
        L--;
        R++;
    }

    return R - L - 1;
}

/**
 * @param {string} s
 * @return {string}
 */
var longestPalindrome = function(s) {
    if (s === null || s.length < 1) return "";
    let start = 0, end = 0;
    for (let i = 0; i < s.length; i++) {
        let len1 = expandAroundCenter(s, i, i);
        let len2 = expandAroundCenter(s, i, i+1);
        let len = Math.max(len1, len2);
        if (len > end - start) {
            start = i - Math.floor((len - 1) / 2);
            end = i + Math.floor(len / 2);
        }
    }

    return s.substring(start, end+1);
};

猜你喜欢

转载自blog.csdn.net/crf_moonlight/article/details/82716683