题目链接:https://leetcode.com/problems/longest-palindromic-substring/

题意很简单,就是求一个字符串得最长子串,这里的子串指连续的。

本文给出四个不同时间的解法。在LeetCode上的用时分别是500ms,250ms,60ms以及6ms。

(1)500ms-最朴素解法

这种解法相当于模拟求解了,是一种正向思维,即枚举所有起点和终点,判断长度是否最长,且是回文的。时间复杂度O(n3).代码如下:

 class Solution {
public:
string longestPalindrome(string s) {
int maxlen = ;
int len = s.length();
string ans;
int r = ,l = ; for(int i = ; i < len; i++)
{
for(int j = len - ; j > i; j--)
{
if (j - i + <= maxlen) break;
bool flag = ;
for(int k = ; k < (j - i + ) / ; k++)
{
if(s[i + k] != s[j - k])
{
flag = ;
break;
}
}
if(flag == )
{
maxlen = j - i + ;
l = i;
r = j;
}
}
}
return s.substr(l,r - l + );
}
};

(2)250ms----DP

以空间换时间,定义一个布尔类型的数组p[][],负责存储以 i、j 为左右界的子串是否为回文的。然后再遍历一遍,寻找是回文且最长的。时间复杂度O(n2)。

在求解 p 数组时,采用的策略是不断扩大 p 的长度,易知:

p[i][i] = true;

p[i][i+1] = (s[i] ==  s[i+1]);

那么,当长度为 k+1 时,有

p[i][i+k] = (p[i + 1][i + k - 1]) && (s[i] == s[i+k]);

从上式可以看出,要求长度为 k+1 时的回文与否,就得知道长度为 k 时的回文与否。因而代码如下:

 class Solution {
public:
string longestPalindrome(string s) {
int maxlen = ;
int len = s.length();
int r = ,l = ;
bool p[][];
for(int i = ; i < len; i ++)
{
p[i][i] = true;
p[i][i+] = s[i] == s[i+];
}
for(int k = ; k < len; k++)
{
for(int i = ; i < len && i + k < len; i++)
{
p[i][i+k] = s[i] == s[i+k] && p[i+][i+k-];
}
}
for(int i = ; i < len; i++)
for(int j = ; j < len; j ++)
if(p[i][j] && j - i + > maxlen)
{
l = i;
r = j;
maxlen = j - i + ;
} return s.substr(l,r - l + );
}
};

(3)60ms---中心扩展法

前面两种都是正向思维,后面这两种是以解为起点,逆向构造回文子串。解法(3)最坏时间复杂度是O(n2),虽然时间复杂度与解法(2)是一样的,但是逆向求解很大程度上减少了遍历的次数,达不到回文的基本条件就不会继续扩展,在很大程度上降低了时间代价。

这种解法也可叫做从中间扩散(ExpandAroundCenter)。奇数子串:以 i 为中心,向外扩展;偶数子串:以 (i,i+1)为中心,向外扩展。扩展时满足:左右界不超出字符串边界且对称相等。以上述方法算出以 i 为中心的奇/偶数子串中长的一个作为当前的回文子串长度temp,然后比较temp与maxlen,重复该步骤求出最终解。

其中,确定了temp后,如何获得该子串的左右界需要考虑一下,举个实例就算出来了:l = i - (temp - 1) / 2, r = temp - 1 + l; 其实 l 算出来了,根据 temp = r - l + 1 就可以求出 r 了。

代码如下:

 class Solution {
public:
string longestPalindrome(string s) {
int maxlen = ;
int len = s.length();
int r = ,l = ;
for(int i = ; i < len; i ++)
{
int temp = max(expandAroundCenter(s,i,i),expandAroundCenter(s,i,i+));
if(temp > maxlen)
{
l = i - (temp - ) / ;
r = temp - + l;
maxlen = temp;
}
}
return s.substr(l,r - l + );
}
private:
int expandAroundCenter(string s, int l, int r)
{
while(l >= && r < s.length() && s[l] == s[r])
{
l--;
r++;
}
return r - l - ;
}
};

(4)6ms---改进的中心扩展法

由解法(1)到解法(3)的过程中可以看出,缩短时间的思想是不断减少不必要的计算或重复的计算。解法(4)就是在解法(3)的基础上进一步缩减重复的计算。缩减的策略是,不是以一个字符 i 为中心计算其奇数或偶数长度的回文子串,而是以一个由相同字符组成的连续子串为中心向外扩展。仔细想想其实是很有道理的。字符个数总共只有128个,当字符串长度很大时,构成回文子串的字符中最有可能是重复的字符反复出现。从最终的运行时间可能看出这种策略的优势,比解法(3)平均缩短了10倍的时间。

代码如下:

 class Solution {
public:
std::string longestPalindrome(std::string s) {
if (s.size() < )
return s;
int len = s.size(), max_left = , max_len = , left, right;
for (int start = ; start < len && len - start > max_len / ;) {
left = right = start;
while (right < len - && s[right + ] == s[right])//求出重复字符组成的子串的右界
++right;
start = right + ;//下一轮遍历的起点。
while (right < len - && left > && s[right + ] == s[left - ]) {//不断向外扩展
++right;
--left;
}
if (max_len < right - left + ) {
max_left = left;
max_len = right - left + ;
}
}
return s.substr(max_left, max_len);
}
};

总结:主动寻找构造解的方式 比 被动搜索解的方式 效率更高!

LeetCode5. Longest Palindromic Substring 最长回文子串 4种方法的更多相关文章

  1. Longest Palindromic Substring (最长回文字符串)——两种方法还没看,仍需认真看看

    Given a string S, find the longest palindromic substring in S. You may assume that the maximum lengt ...

  2. Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法)

    Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...

  3. LeetCode-5:Longest Palindromic Substring(最长回文子字符串)

    描述:给一个字符串s,查找它的最长的回文子串.s的长度不超过1000. Input: "babad" Output: "bab" Note: "aba ...

  4. LeetCode:Longest Palindromic Substring 最长回文子串

    题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...

  5. lintcode :Longest Palindromic Substring 最长回文子串

    题目 最长回文子串 给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串. 样例 给出字符串 "abcdzdcab",它的最长回文 ...

  6. [leetcode]5. Longest Palindromic Substring最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  7. 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  8. [LeetCode] 5. Longest Palindromic Substring 最长回文子串

    Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...

  9. 【LeetCode】5. Longest Palindromic Substring 最长回文子串

    作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...

随机推荐

  1. iOS开发之判断系统版本

    if([[UIDevice currentDevice].systemVersion doubleValue]>=7.0) { //是IOS7至以上版本 }else{ //IOS7以下版本 }

  2. 一个基于php+mysql的外卖订餐网站(带源码)

    订饭组 一个基于php+mysql的外卖订餐网站,包括前端和后台.源码地址 源码演示地址:http://dingfanzu.com 商家后台系统:http://dingfanzu.com/admin ...

  3. 深入理解ajax系列第九篇——jQuery中的ajax

    前面的话 jQuery提供了一些日常开发中需要的快捷操作,例如load.ajax.get和post等,使用jQuery开发ajax将变得极其简单.这样开发人员就可以将程序开发集中在业务和用户体验上,而 ...

  4. java iframe 嵌套,session失效重新登录页面嵌套问题

    将后台跳转改写成 PrintWriter out = response.getWriter(); out.println("<html>");    out.print ...

  5. 【Egret】2D 使用中的一些疑难解决技巧!

    1.问题:声音在ios上无法播放    解决方法:①首先需要预加载一个声音                        ②然后目前只有点击之后才能播放声音,不能默认播放 2.问题:滚动条问题   解 ...

  6. Java基础之J2EE规范

    什么是J2EE? 在企业级应用中,都有一些通用企业需求模块,如数据库连接,邮件服务,事务处理等.既然很多企业级应用都需要这些模块,一些大公司便开发了自己的通用模块服务,即中间件.这样一来,就避免了重复 ...

  7. Java中利用BigInteger类进行大数开方

    在Java中有时会用到大数据,基本数据类型的存储范围已经不能满足要求了,如要对10的1000次方的这样一个数据规模的数进行开方运算,很明显不能直接用Math.sqrt()来进行计算,因为已经溢出了. ...

  8. mac jmeter 的使用

    1.下载 mac下载地址:http://jmeter.apache.org/download_jmeter.cgi,下载apache-jmeter-3.1.tgz 2.下载完毕后解压,得到安装包 3. ...

  9. mac上使用使用rz,sz命令

    mac上使用rz,sz命令,mac上的终端不支持rz 和sz,所以安装iterm并配置使用rz和cz 1.首先需要下载安装iterm2,下载地址:下载后安装 http://www.iterm2.cn/ ...

  10. 关于下拉框列表不可选择相同值的设置一:当前DOM不可选

    <!DOCTYPE html><html><head lang="en"> <meta charset="UTF-8" ...