【一天一道LeetCode】#5 Longest Palindromic Substring
一天一道LeetCode系列
(一)题目
Given a string S, find the longest palindromic substring in S. You may
assume that the maximum length of S is 1000, and there exists one
unique longest palindromic substring.
题意:求一个字符串的最长回文字串。
(二)解题
1.中心扩展法
看到这个题首先想到的就是中心扩展法,遍历每一个字符,然后以该字符为中心向四周扩展,这种方法的时间复杂度为O(N^2),但是需要注意的是,奇数和偶数回文字符串需要区别对待,如aba和abba都是回文字符串。
class Solution {
public:
string longestPalindrome(string s) {
int max1=0;//奇数最长子串
int max2=0;//偶数最长子串
int idx1=0;//奇数最长子串的中心字符
int idx2=0;//偶数最长子串的中心字符
string result;
for(int i = 0 ; i < s.length() ; ++i)
{
int j = i;
int z = i;
int count1=0;
int count2=0;
//计算奇数最长回文字符串
while((++z<s.length()) && (--j>=0) && (s[z] == s[j]))
{
count1+=2;
if(count1 > max1)
{
max1=count1;
idx1 = i;
}
}
//计算偶数最长回文字符串
j = i;
z = i+1;
while((z<s.length()) && (j>=0) &&(s[z] == s[j]))
{
count2+=2;
if(count2 > max2)
{
max2=count2;
idx2 = i;
}
z++;
j--;
}
}
if(max1+1>max2) result = s.substr(idx1-max1/2,max1+1);
else result = s.substr(idx2-max2/2+1,max2);
return result;
}
};
2.中心扩展法的优化
区分奇数和偶数显得程序比较臃肿,我们可以利用“改造“字符串来避免这种情况。如aba改成#a#b#a#,abba改成#a#b#b#a,这样就不用区分奇偶了。
class Solution {
public:
string longestPalindrome(string s) {
int max=0;
int idx=0;
string temp[2005];
//改造字符串
int j = 0;
for(int i = 0; i < s.length() ; ++i)
{
temp[j++] = '#';
temp[j++] = s[i];
}
temp[j++] = '#';
temp[j] = '\0';
for(int i = 0 ; i <2*s.length()+1 ; ++i)
{
int j = i;
int z = i;
int count=0;
//计算奇数最长回文字符串
while((++z<(2*s.length()+1)) && (--j>=0) && (temp[z] == temp[j]))
{
count++;
if(count > max)
{
max=count;
idx = i;
}
}
}
return s.substr((idx-max)/2,max);
}
};
3.动态规划法
DP算法的思想就是记录每一个回文子串的位置,在每一次判断是否为回文子串的时候先判断它的子串是不是回文,例如,用map[i][j]记录i到j为回文数组,如果这个时候s[i-1]==s[j+1],那么就能在O(1)时间内判断[i-1,j+1]是否为回文了。
动态规划法的时间复杂度为O(n^2).
class Solution {
public:
string longestPalindrome(string s) {
int len = s.length();
int idx = 0;//记录最长回文字符的开始处
int max = 1;//记录最长回文字符的长度
int map[1000][1000] = {0};//记录i到j是否为回文子串
for(int i = 0 ; i < len ; ++i)
{
map[i][i] = 1;//初始化长度为1的回文子串
}
for(int i = 0 ; i < len ; ++i)
{
if(s[i] == s[i+1])//初始化长度为2的子串
{
map[i][i+1] = 1;
idx = i;
max = 2;
}
}
for(int plen = 3 ; plen <= len ; plen++)//从长度为3开始算起
{//plen代表当前判断的回文子串的长度
for(int j = 0 ; j < len - plen +1 ; j++)
{
int z = plen+j-1;//z为回文子串的尾序号
if (s[j] == s[z] && map[j+1][z-1]) {
//O(1)时间内判断j到z是否回文
map[j][z] = 1;
idx = j;
max = plen;
}
}
}
return s.substr(idx,max);//返回子串
}
};
4.经典的Manacher算法,O(n)复杂度
算法步骤:
step1:跟解法2一样,改造字符串:
abba –> $#a#b#b#a#
注:加’$’是为了避免处理越界问题
step2:用p[i]记录以i为中心点的回文字符串长度
改造后的字符串:$#a#b#b#a#
p[]数组的值:121242121
注:p[i]-1 = 源字符串中回文子串长度
step3:利用DP的思想来求解p[]
利用中心扩展法求以i为中心的最长回文串
while(i+p[i] < temps.length() && temps[i-p[i]] == temps[i+p[i]]) p[i]++;
利用p[],mx,id记录的已有回文字符串的长度来避免大量重复的匹配
if(mx > i) p[i] = p[2*id-i] < (mx-i) ? p[2*id-i]:(mx-i);
注:p[2*id-i]为i关于j对称的点的回文串长度
mx为i之前的回文串延伸到右边的最长位置,id为该回文串的中间值
class Solution {
public:
string longestPalindrome(string s) {
string temps;
temps+="$#";//加$是为了避免处理越界情况,减小时间复杂度
for(int i = 0 ; i < s.length() ; ++i)//
{
temps+=s[i];
temps+="#";
}
int *p = new int[temps.length()];//p[i]记录以i为中心的回文串长度
memset(p, 0, sizeof(p));
int max = 0,idx = 0;//max记录最长回文串的长度,idx记录最长回文串的中心位置
int mx = 0,id = 0;//mx记录i之前的最长回文串延伸到最右边的位置,id记录该字符串的中心位置
for(int i = 1; i < temps.length() ; ++i)
{
if(mx > i)
{
p[i] = p[2*id-i] < (mx-i) ? p[2*id-i]:(mx-i);
}
else
p[i] = 1;
while(i+p[i] < temps.length() && temps[i-p[i]] == temps[i+p[i]])
{
p[i]++;
}
if(i+p[i]>mx)
{
id = i;
mx = i+p[i];
if(p[i]>max)
{
max = p[i];
idx = id;
}
}
}
max--;
return s.substr((idx-max)/2,max);
}
};
该算法的时间复杂度为O(n)。
以上代码在LeetCode中均Accepted。
【一天一道LeetCode】#5 Longest Palindromic Substring的更多相关文章
- LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法
LeetCode(4) || Longest Palindromic Substring 与 Manacher 线性算法 题记 本文是LeetCode题库的第五题,没想到做这些题的速度会这么慢,工作之 ...
- Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)
Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...
- 求最长回文子串 - leetcode 5. Longest Palindromic Substring
写在前面:忍不住吐槽几句今天上海的天气,次奥,鞋子里都能养鱼了...裤子也全湿了,衣服也全湿了,关键是这天气还打空调,只能瑟瑟发抖祈祷不要感冒了.... 前后切了一百零几道leetcode的题(sol ...
- LeetCode 5 Longest Palindromic Substring(最长子序列)
题目来源:https://leetcode.com/problems/longest-palindromic-substring/ Given a string S, find the longest ...
- 【JAVA、C++】LeetCode 005 Longest Palindromic Substring
Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...
- leetcode:Longest Palindromic Substring(求最大的回文字符串)
Question:Given a string S, find the longest palindromic substring in S. You may assume that the maxi ...
- [LeetCode][Python]Longest Palindromic Substring
# -*- coding: utf8 -*-'''__author__ = 'dabay.wang@gmail.com'https://oj.leetcode.com/problems/longest ...
- 【LeetCode】Longest Palindromic Substring 解题报告
DP.KMP什么的都太高大上了.自己想了个朴素的遍历方法. [题目] Given a string S, find the longest palindromic substring in S. Yo ...
- [LeetCode] 5. Longest Palindromic Substring 最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 最长回文子串-LeetCode 5 Longest Palindromic Substring
题目描述 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
随机推荐
- Android Material Design(一)史上最全的材料设计控件大全
主要内容: 本文将要介绍Material design和Support library控件,主要包括TextInputLayout.SwitchCompat.SnackBar.FloatingActi ...
- Swift类中如何创建一个对外只读对内可读写的属性
很简单用private修饰符,后面跟限制关键字set: class Day{ private(set) var rawValue:Int = 0 func showRawValue(){ print( ...
- 剑指Offer——网易笔试题+知识点总结
剑指Offer--网易笔试题+知识点总结 Fibonacci package cn.edu.ujn.nk; import java.util.ArrayList; import java.util.S ...
- String放入运行时常量池的时机与String.intern()方法解惑
运行时常量池概述 Java运行时常量池中主要存放两大类常量:字面量和符号引用.字面量比较接近于Java语言层面的常量概念,如文本字符串.声明为final的常量值等. 而符号引用则属于编译原理方面的概念 ...
- Dynamics CRM 插件注册时报Assembly must be registered in isolation的解决方法
在插件注册的时候经常会遇到"Assembly must be registered in isolation"的问题导致无法注册,之前经常会被同事或者朋友问到这个问题,遇到这个问题 ...
- Android简易实战教程--第二十六话《网络图片查看器在本地缓存》
本篇接第二十五话 点击打开链接 http://blog.csdn.net/qq_32059827/article/details/52389856 上一篇已经把王略中的图片获取到了.生活中有这么 ...
- 4.QT中进程操作,线程操作
QT中的线程操作 T19Process.pro SOURCES += \ main.cpp CONFIG += C++11 main.cpp #include <QCoreApplicat ...
- HTML5中 HTML格式化/HTML样式/链表/表格-样式 韩俊强的博客
HTML5学习从简单到复杂,循环渐进! 每日更新关注:http://weibo.com/hanjunqiang 新浪微博! 1.HTML格式化 <!DOCTYPE html> <h ...
- UNIX网络编程——套接字选项(SO_REUSEADDR)
1.一般来说,一个端口释放后会等待两分钟之后才能再被使用,SO_REUSEADDR是让端口释放后立即就可以被再次使用. SO_REUSEADDR用于对TCP套接字处于TIME_WAIT状态下的sock ...
- 如何让 jQuery Mobile 不显示讨厌的 loading 界面
jQuery Mobile 的一个BUG: 当不采用 ajax 以及 他自己的 back 返回的时候,即: 点击浏览器后退按钮时,将会从缓存之中加载页面,此时,讨厌的 loading 动画出来了,而且 ...