这是我参与11月更文挑战的第15天,活动详情查看:2021最后一次更文挑战
前言
关于 LeetCode 数组类型题目的相关解法,可见LeetCode 数组类型题目做前必看,分类别解法总结了题目,可以用来单项提高。觉得有帮助的话,记得多多点赞关注哦,感谢!
题目描述
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
示例 2:
输入:s = "cbbd"
输出:"bb"
示例 3:
输入:s = "a"
输出:"a"
示例 4:
输入:s = "ac"
输出:"a"
链接:leetcode-cn.com/problems/lo…
题解
-
暴力解法。暴力解法的想法就是找出所有的子串,然后判断每个字串是不是回文串,记录并返回最长的回文串。
找出所有子串的时间复杂度为 O(n^2),判断是不是回文串时间复杂度为 O(n),所以整体的时间复杂度为 O(n^3)。
具体代码如下,其中做了一个剪枝操作,只有当前的字串长度大于当前最长的回文串长度时才需要判断是不是回文串,否则没有必要判断。
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
let ans = ''
const n = s.length
for (let i = 0; i < n; i++) {
for (let j = i; j < n; j++) {
// 剪枝
if ((j - i + 1) > ans.length) {
if (isPalindrome(s, i, j)) {
ans = s.slice(i, j + 1)
}
}
}
}
return ans
};
var isPalindrome = (s, l, r) => {
while (l < r) {
if (s[l] !== s[r]) {
return false
}
l++
r--
}
return true
}
-
扩展法。暴力方法中,我们每次都从头计算每个字串是不是回文串,没有很好的利用之前的比较,所以会有多余的计算。
可以换个思路,我们从中间向两边扩展这个回文串。如果两边字符相同,就继续扩展,这样其实是利用了之前的比较。
由于回文串有可能是奇数,也有可能是偶数,所以每次扩展包括一个中心和两个中心两个扩展。
具体代码如下,时间复杂度 O(n^2)
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function(s) {
let ansLen = 0
let start = 0
const n = s.length
for (let i = 0; i < n; i++) {
let now = Math.max(getLen(s, i, i), getLen(s, i, i+1))
if (now < ansLen) continue
start = i - Math.floor((now - 1) / 2)
ansLen = now
}
return s.slice(start, start + ansLen)
};
var getLen = (s, i, j) => {
while ( i >= 0 && j < s.length && s[i] === s[j]) {
i--
j++
}
return j - i - 1
}