第五章 - 高频考题(中等)
1906. 查询差绝对值的最小值
0005. 最长回文子串

题目地址(5. 最长回文子串)

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。
示例 1:
输入: "babad" 输出: "bab" 注意: "aba" 也是一个有效答案。 示例 2:
输入: "cbbd" 输出: "bb"

前置知识

  • 回文

公司

  • 阿里
  • 百度
  • 腾讯

思路

这是一道最长回文的题目,要我们求出给定字符串的最大回文子串。
5.longest-palindromic-substring
解决这类问题的核心思想就是两个字“延伸”,具体来说如果在一个不是回文字符串的字符串两端添加任何字符,或者在回文串左右分别加不同的字符,得到的一定不是回文串
5.longest-palindromic-substring-2
base case 就是一个字符(轴对称点是本身),或者两个字符(轴对称点是介于两者之间的虚拟点)。
5.longest-palindromic-substring-3
事实上,上面的分析已经建立了大问题和小问题之间的关联,基于此,我们可以建立动态规划模型。
我们可以用 dp[i][j] 表示 s 中从 i 到 j(包括 i 和 j)是否可以形成回文, 状态转移方程只是将上面的描述转化为代码即可:
1
if (s[i] === s[j] && dp[i + 1][j - 1]) {
2
dp[i][j] = true;
3
}
Copied!

关键点

  • ”延伸“(extend)

代码

代码支持:Python,JavaScript,CPP
Python Code:
1
class Solution:
2
def longestPalindrome(self, s: str) -> str:
3
n = len(s)
4
if n == 0:
5
return ""
6
res = s[0]
7
def extend(i, j, s):
8
while(i >= 0 and j < len(s) and s[i] == s[j]):
9
i -= 1
10
j += 1
11
return s[i + 1:j]
12
13
for i in range(n - 1):
14
e1 = extend(i, i, s)
15
e2 = extend(i, i + 1, s)
16
if max(len(e1), len(e2)) > len(res):
17
res = e1 if len(e1) > len(e2) else e2
18
return res
Copied!
JavaScript Code:
1
/*
2
* @lc app=leetcode id=5 lang=javascript
3
*
4
* [5] Longest Palindromic Substring
5
*/
6
/**
7
* @param {string} s
8
* @return {string}
9
*/
10
var longestPalindrome = function (s) {
11
// babad
12
// tag : dp
13
if (!s || s.length === 0) return "";
14
let res = s[0];
15
16
const dp = [];
17
18
// 倒着遍历简化操作, 这么做的原因是dp[i][..]依赖于dp[i + 1][..]
19
for (let i = s.length - 1; i >= 0; i--) {
20
dp[i] = [];
21
for (let j = i; j < s.length; j++) {
22
if (j - i === 0) dp[i][j] = true;
23
// specail case 1
24
else if (j - i === 1 && s[i] === s[j]) dp[i][j] = true;
25
// specail case 2
26
else if (s[i] === s[j] && dp[i + 1][j - 1]) {
27
// state transition
28
dp[i][j] = true;
29
}
30
31
if (dp[i][j] && j - i + 1 > res.length) {
32
// update res
33
res = s.slice(i, j + 1);
34
}
35
}
36
}
37
38
return res;
39
};
Copied!
CPP Code:
1
class Solution {
2
private:
3
int expand(string &s, int L, int R) {
4
while (L >= 0 && R < s.size() && s[L] == s[R]) {
5
--L;
6
++R;
7
}
8
return R - L - 1;
9
}
10
public:
11
string longestPalindrome(string s) {
12
if (s.empty()) return s;
13
int start = 0, maxLen = 0;
14
for (int i = 0; i < s.size(); ++i) {
15
int len1 = expand(s, i, i);
16
int len2 = expand(s, i, i + 1);
17
int len = max(len1, len2);
18
if (len > maxLen) {
19
start = i - (len - 1) / 2;
20
maxLen = len;
21
}
22
}
23
return s.substr(start, maxLen);
24
}
25
};
Copied!
复杂度分析
  • 时间复杂度:$O(N^2)$
  • 空间复杂度:$O(N^2)$

相关题目

大家对此有何看法,欢迎给我留言,我有时间都会一一查看回答。更多算法套路可以访问我的 LeetCode 题解仓库:https://github.com/azl397985856/leetcode 。 目前已经 37K star 啦。 大家也可以关注我的公众号《力扣加加》带你啃下算法这块硬骨头。