LeetCode.5-最长回文子串(Longest Palindromic Substring)
这是悦乐书的第342次更新,第366篇原创
01 看题和准备
今天介绍的是LeetCode算法题中Medium级别的第3题(顺位题号是5)。给定一个字符串s,找到s中最长的回文子字符串。 您可以假设s的最大长度为1000。例如:
输入:“babad”
输出:“bab”
注意:“aba”也是一个有效的答案。
输入:“cbbd”
输出:“bb”
02 第一种解法
暴力解法。
使用两层循环截取出所有的子串,判断该子串是否是回文,从中取长度最长的子串作为结果输出。
此解法时间复杂度是O(N^3),空间复杂度是O(1)。
public String longestPalindrome(String s) {
int max = 0, n = s.length();
String result = "";
for (int i=0; i<n; i++) {
for (int j=i+1; j<=n; j++) {
String tem = s.substring(i,j);
if (isPalindrome(tem)) {
if (j-i > max) {
max = j-i;
result = tem;
}
}
}
}
return result;
}
public boolean isPalindrome(String s){
int left = 0, right = s.length()-1;
while (left < right) {
if (s.charAt(left) != s.charAt(right)) {
return false;
}
left++;
right--;
}
return true;
}
03 第二种解法
我们也可以换一种找回文的方式,从左右两边向中间变成由中间向左右两边。
此时需要考虑回文的长度是奇数还是偶数的情况,如果是奇数形回文,就以当前字符为中心左右两边寻找,例如回文"bab";如果是偶数形回文,需要两个字符,并且这两个字符是相等的,则需要以当前字符和其相邻的字符为中心向左右两边寻找,例如回文"abba"。
此解法的时间复杂度是O(N^2),空间复杂度是O(1)。
public String longestPalindrome2(String s) {
if (s.length() < 2) {
return s;
}
int n = s.length(), start = 0, end = 0;
for (int i=0; i<n-1; i++) {
int len = helper(s, i, i);
int len2 = helper(s, i, i+1);
int len3 = Math.max(len, len2);
if (len3 > end - start) {
start = i - (len3-1)/2;
end = i + len3/2;
}
}
return s.substring(start, end+1);
}
/**
* 以当前字符为中心向左右两边扩散,寻找回文子串
* @param s 字符串
* @param left 起始索引
* @param right 结束索引
* @return 回文子串长度
*/
public int helper(String s, int left, int right) {
int n = s.length(), L = left, R = right;
while (L >= 0 && R < n && s.charAt(L) == s.charAt(R)) {
// 继续向左寻找
L--;
// 继续向右寻找
R++;
}
return R - L -1;
}
04 第三种解法
动态规划算法,用空间换时间,是对第一种解法的改进。
此解法的时间复杂度是O(N^2),空间复杂度是O(N^2)。
public String longestPalindrome3(String s) {
if (s.length() < 2) {
return s;
}
int n = s.length(), start = 0, end = 0;
int maxLen = 0;
// dp[j][i]表示子串[j,i]是回文
boolean[][] dp = new boolean[n][n];
// 右边界
for (int i=0; i<n; i++) {
// 左边界
for (int j=i; j>=0; j--) {
if (i == j) {
dp[j][i] = true;
} else if (s.charAt(i) == s.charAt(j)) {
// 回文中至少3个字符
if (j < i-1) {
dp[j][i] = dp[j+1][i-1];
} else {
dp[j][i] = true;
}
} else {
dp[i][j] = false;
}
// 比较最大值,并重新赋值
if (i-j+1 > maxLen && dp[j][i]) {
maxLen = i-j+1;
start = j;
end = i;
}
}
}
return s.substring(start, end+1);
}
05 第四种解法
马拉车算法(Manacher's Algorithm),来自于讨论区,这是第一次听说这种算法,将时间复杂度降低到了O(N),也是很厉害了,后续抽时间来详细了解下这个算法。
public String longestPalindrome4(String s) {
String T = preProcess(s);
int n = T.length();
int[] P = new int[n];
int C = 0, R = 0;
for (int i = 1; i < n - 1; i++) {
int i_mirror = 2 * C - i;
if (R > i) {
P[i] = Math.min(R - i, P[i_mirror]);
} else {
P[i] = 0;
}
while (T.charAt(i + 1 + P[i]) == T.charAt(i - 1 - P[i])) {
P[i]++;
}
if (i + P[i] > R) {
C = i;
R = i + P[i];
}
}
int maxLen = 0;
int centerIndex = 0;
for (int i = 1; i < n - 1; i++) {
if (P[i] > maxLen) {
maxLen = P[i];
centerIndex = i;
}
}
int start = (centerIndex - maxLen) / 2;
return s.substring(start, start + maxLen);
}
/**
*
* @param s
* @return
*/
public String preProcess(String s) {
int n = s.length();
if (n == 0) {
return "^$";
}
String ret = "^";
for (int i = 0; i < n; i++) {
ret += "#" + s.charAt(i);
}
ret += "#$";
return ret;
}
06 小结
算法专题目前已连续日更超过六个月,算法题文章211+篇,公众号对话框回复【数据结构与算法】、【算法】、【数据结构】中的任一关键词,获取系列文章合集。
以上就是全部内容,如果大家有什么好的解法思路、建议或者其他问题,可以下方留言交流,点赞、留言、转发就是对我最大的回报和支持!
LeetCode.5-最长回文子串(Longest Palindromic Substring)的更多相关文章
- [译+改]最长回文子串(Longest Palindromic Substring) Part II
[译+改]最长回文子串(Longest Palindromic Substring) Part II 原文链接在http://leetcode.com/2011/11/longest-palindro ...
- [译]最长回文子串(Longest Palindromic Substring) Part I
[译]最长回文子串(Longest Palindromic Substring) Part I 英文原文链接在(http://leetcode.com/2011/11/longest-palindro ...
- 领扣-5 最长回文子串 Longest Palindromic Substring MD
Markdown版本笔记 我的GitHub首页 我的博客 我的微信 我的邮箱 MyAndroidBlogs baiqiantao baiqiantao bqt20094 baiqiantao@sina ...
- 最长回文子串(Longest Palindromic Substring)-DP问题
问题描述: 给定一个字符串S,找出它的最大的回文子串,你可以假设字符串的最大长度是1000,而且存在唯一的最长回文子串 . 思路分析: 动态规划的思路:dp[i][j] 表示的是 从i 到 j 的字串 ...
- [Swift]LeetCode5. 最长回文子串 | Longest Palindromic Substring
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 【算法】最长回文子串 longest palindrome substring
对于字符串S, 要找到它最长的回文子串,能想到的最暴力方法,应该是对于每个元素i-th都向左向右对称搜索,最后用一个数组span 记录下相对应元素i-th为中心的回文子串长度. 那么问题来了: 1. ...
- LeetCode:最长回文子串【5】
LeetCode:最长回文子串[5] 题目描述 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为1000. 示例 1: 输入: "babad" 输出: ...
- 【LeetCode】最长回文子串【动态规划或中心扩展】
给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad"输出: "bab"注意: " ...
- Java实现 LeetCode 5 最长回文子串
5. 最长回文子串 给定一个字符串 s,找到 s 中最长的回文子串.你可以假设 s 的最大长度为 1000. 示例 1: 输入: "babad" 输出: "bab&quo ...
随机推荐
- acedinitget
// 提示用户选择选择方式 acedInitGet(0, _T("W CP")); int nRs = acedGetKword(_T("\n请输入关键字确定选择方式[窗 ...
- Android 双屏异显
android双屏是克隆模式,如果要在第二屏幕显示不同内容,需要自定义一个Presentation类 1.先设置权限 (刚开始折腾很久没有效果,后来发现是没设置权限) <!-- 显示系统窗口权限 ...
- MIUI 的参与感
最近这段时间在看小米联合创始人黎万强写的<参与感>这本书,看完我还挺有感触的.小米相信大家都一定有所耳闻. 2010 年 4 月 6 日 小米公司正式创立. 8 月 ...
- 所有对象的父类(java.lang.Object)
一.介绍 Object类是类层次结构的根源,每一个类都存在一个父类为Object类.所有的对象,包括数组,都实现了 Object 类的方法. 二.对象初始化 这里使用了静态代码块进行Object类的初 ...
- 转载:python 日期,季度,年份
# 这个data_matrix[:,dimen] <= thresh_val 内标会返回data_matrix当中的值符合条件的,返回为True # ret_array 中就会返回 下标为Tru ...
- 基于jquery的常见函数封装
/// <reference path="jquery-1.8.0.min.js" />/** DIV或元素居中* @return*/jQuery.fn.mCenter ...
- Windows Server 2008安装教程
系统简介 windows server 2008是迄今为止最灵活.最稳定的windows 操作系统.Windows server 2008 的安装过程是基于镜像文件的,主要版本:Windows Ser ...
- 《hello-world》第八次团队作业:Alpha冲刺-Scrum Meeting 3
项目 内容 这个作业属于哪个课程 2016级计算机科学与工程学院软件工程(西北师范大学) 这个作业的要求在哪里 实验十二 团队作业8:软件测试与Alpha冲刺 团队名称 <hello--worl ...
- JavaSE 学习笔记之package包(十一)
包:定义包用package关键字. 1:对类文件进行分类管理. 2:给类文件提供多层名称空间. 如果生成的包不在当前目录下,需要最好执行classpath,将包所在父目录定义到classpath变量中 ...
- Python 3 条件语句
条件语句: 用于判定,判定是否符合某条件,符合则执行,不符合则不执行该条件所定义的操作. 一步判定: 用于理解不会这样使用. if 1==1: if条件判定只能出现一次. print(&q ...