其他
005. 最长回文子串 | Leetcode题解
点击上方“蓝色字体”,选择“设为星标”
每天复习一道面试题,轻松拿大厂Offer~
题目描述
给定一个字符串 s
,找到 s
中最长的回文子串。你可以假设 s
的最大长度为 1000。
示例 1:
输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。
示例 2:
输入: "cbbd"
输出: "bb"
难度:
难度:中等 支持语言:JavaScript、Java、Python
相关标签
回文 动态规划 字符串
相关企业
阿里 百度 腾讯
思路
这是一道最长回文的题目,要我们求出给定字符串的最大回文子串。
解决这类问题的核心思想就是两个字“延伸”,具体来说如果在一个不是回文字符串的字符串两端添加任何字符,或者在回文串左右分别加不同的字符,得到的一定不是回文串
base case 就是一个字符(轴对称点是本身),或者两个字符(轴对称点是介于两者之间的虚拟点)。
事实上,上面的分析已经建立了大问题和小问题之间的关联,基于此,我们可以建立动态规划模型。
我们可以用 dp[i][j] 表示 s 中从 i 到 j(包括 i 和 j)是否可以形成回文, 状态转移方程只是将上面的描述转化为代码即可:
if (s[i] === s[j] && dp[i + 1][j - 1]) {
dp[i][j] = true;
}
或 暴力匹配 (Brute Force)
根据回文子串的定义,枚举所有长度大于等于 22 的子串,依次判断它们是否是回文;
在具体实现时,可以只针对大于“当前得到的最长回文子串长度”的子串进行“回文验证”;
在记录最长回文子串的时候,可以只记录“当前子串的起始位置”和“子串长度”,不必做截取。这一步我们放在后面的方法中实现。
关键点
”延伸“(extend)
复杂度分析
时间复杂度: 空间复杂度:
代码
JavaScript 实现
/**
* @来源:Javascript中文网 - 前端进阶资源教程 https://www.javascriptc.com/
* @介绍:前端中文网是以前端进阶资源教程分享为主的专业网站,包括:前端、大厂面试题、typescript教程、程序人生、React.js
* @lc app=leetcode id=5 lang=javascript
*
* [5] Longest Palindromic Substring
*/
/**
* @param {string} s
* @return {string}
*/
var longestPalindrome = function (s) {
// babad
// tag : dp
if (!s || s.length === 0) return "";
let res = s[0];
const dp = [];
// 倒着遍历简化操作, 这么做的原因是dp[i][..]依赖于dp[i + 1][..]
for (let i = s.length - 1; i >= 0; i--) {
dp[i] = [];
for (let j = i; j < s.length; j++) {
if (j - i === 0) dp[i][j] = true;
// specail case 1
else if (j - i === 1 && s[i] === s[j]) dp[i][j] = true;
// specail case 2
else if (s[i] === s[j] && dp[i + 1][j - 1]) {
// state transition
dp[i][j] = true;
}
if (dp[i][j] && j - i + 1 > res.length) {
// update res
res = s.slice(i, j + 1);
}
}
}
return res;
};
/**
* @作者:salter
* @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-chuan-by-fanzhanxiang/
*/
var longestPalindrome = function(s) {
let ans = '';
let n = s.length;
let dp = Array.from(new Array(n), () => new Array().fill(0));
for(let i = n-1; i >=0; i--) {
for(let j = i; j < n; j++) {
dp[i][j] = s[i] === s[j] && ( j - i < 2 || dp[i+1][j-1])
if(dp[i][j] && j - i + 1 > ans.length) {
ans = s.substr(i,j - i + 1);
}
}
}
return ans;
}
/**
* @作者:liuxukang
* @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-pu-tong-de-dong-tai-gui-hua-by-liuxukang/
*/
var longestPalindrome = function (s) {
if(!s && s < 2) return s
let len = s.length;
let start = 0
let end = 0;
const calcPalindrome = (left,right) => {
while(left >=0 && right < len && s[left] === s[right]){
left--;
right++;
}
return right -left -1
}
for(let i = 0; i < len; i++) {
let s1 = calcPalindrome(i,i)
let s2 = calcPalindrome(i,i+1)
let maxLen = Math.max(s1,s2)
if(maxLen > end -start ) {
start = i - Math.floor((maxLen - 1) / 2)
end = i + Math.floor(maxLen /2)
}
}
return s.slice(start,end+1)
}
Java 实现
/**
* @作者:windliang
* @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/xiang-xi-tong-su-de-si-lu-fen-xi-duo-jie-fa-bao-gu/
*/
public boolean isPalindromic(String s) {
int len = s.length();
for (int i = 0; i < len / 2; i++) {
if (s.charAt(i) != s.charAt(len - i - 1)) {
return false;
}
}
return true;
}
// 暴力解法
public String longestPalindrome(String s) {
String ans = "";
int max = 0;
int len = s.length();
for (int i = 0; i < len; i++)
for (int j = i + 1; j <= len; j++) {
String test = s.substring(i, j);
if (isPalindromic(test) && test.length() > max) {
ans = s.substring(i, j);
max = Math.max(max, ans.length());
}
}
return ans;
}
/**
* @作者:liweiwei1419
* @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zhong-xin-kuo-san-dong-tai-gui-hua-by-liweiwei1419/
*/
public class Solution {
public String longestPalindrome(String s) {
int len = s.length();
if (len < 2) {
return s;
}
int maxLen = 1;
int begin = 0;
// s.charAt(i) 每次都会检查数组下标越界,因此先转换成字符数组
char[] charArray = s.toCharArray();
// 枚举所有长度大于 1 的子串 charArray[i..j]
for (int i = 0; i < len - 1; i++) {
for (int j = i + 1; j < len; j++) {
if (j - i + 1 > maxLen && validPalindromic(charArray, i, j)) {
maxLen = j - i + 1;
begin = i;
}
}
}
return s.substring(begin, begin + maxLen);
}
/**
* 验证子串 s[left..right] 是否为回文串
*/
private boolean validPalindromic(char[] charArray, int left, int right) {
while (left < right) {
if (charArray[left] != charArray[right]) {
return false;
}
left++;
right--;
}
return true;
}
}
Python 实现
class Solution:
def longestPalindrome(self, s: str) -> str:
n = len(s)
if n == 0:
return ""
res = s[0]
def extend(i, j, s):
while(i >= 0 and j < len(s) and s[i] == s[j]):
i -= 1
j += 1
return s[i + 1:j]
for i in range(n - 1):
e1 = extend(i, i, s)
e2 = extend(i, i + 1, s)
if max(len(e1), len(e2)) > len(res):
res = e1 if len(e1) > len(e2) else e2
return res
# @作者:skay2002
# @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/pythonshuang-bai-50msyi-lun-bian-li-fa-5-zui-chang/
class Solution:
def longestPalindrome(self, s: str) -> str:
if not s: return ""
length = len(s)
if length == 1 or s == s[::-1]: return s
max_len,start = 1,0
for i in range(1, length):
even = s[i-max_len:i+1]
odd = s[i-max_len-1:i+1]
if i - max_len - 1 >= 0 and odd == odd[::-1]:
start = i - max_len - 1
max_len += 2
continue
if i - max_len >= 0 and even == even[::-1]:
start = i - max_len
max_len += 1
continue
return s[start:start + max_len]
# @作者:LeetCode-Solution
# @链接:https://leetcode-cn.com/problems/longest-palindromic-substring/solution/zui-chang-hui-wen-zi-chuan-by-leetcode-solution/
class Solution {
public String longestPalindrome(String s) {
int n = s.length();
boolean[][] dp = new boolean[n][n];
String ans = "";
for (int l = 0; l < n; ++l) {
for (int i = 0; i + l < n; ++i) {
int j = i + l;
if (l == 0) {
dp[i][j] = true;
} else if (l == 1) {
dp[i][j] = (s.charAt(i) == s.charAt(j));
} else {
dp[i][j] = (s.charAt(i) == s.charAt(j) && dp[i + 1][j - 1]);
}
if (dp[i][j] && l + 1 > ans.length()) {
ans = s.substring(i, i + l + 1);
}
}
}
return ans;
}
}
相关题目
516.longest-palindromic-subsequence https://www.javascriptc.com/special/leetcode
其他
原题leetcode链接:https://leetcode-cn.com/problems/longest-palindromic-substring/ 合作方:JavaScript中文网 – 全球极客挚爱的技术成长平台 说明:leetcode 题解 | 每日一题🔥 所有题目并非全部为本人解答,部分为在复习学习中整理提取其他解题作者的优秀笔记,便于大家学习共同进步,如有侵权,请联系删除。