题目链接: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. 兔子生娃问题---函数递归应用--c语言实现

    事情是这样的:在很久很久以前....有一对兔子,从出生后第 3 个月起每个月都生一对兔子,小兔子长到第三个月后每个月又生一对兔子,假如兔子都不死,问每个月的兔子总数为多少? 兔子的规律为数列:1, 1 ...

  2. Linux系统date命令的参数及获取时间戳的方法

    date指令相关用法示例 date 用法: date [OPTION]... [+FORMAT]date [-u|--utc|--universal] [MMDDhhmm[[CC]YY][.ss]] ...

  3. iOS 内存泄漏

      我一直以为现在都是自动内存管理了,还哪有什么内存泄漏啊.一检测才知道,不是我太相信Xcode了,就是我太单纯了.iOS开发中遇到的内存泄漏主要有几下几种: (1)对象不能释放.使用Core Fou ...

  4. vuejs子组件向父组件传递数据

    子组件通过$emit方法向父组件发送数据,子组件在父组件的模板中,通过自定义事件接收到数据,并通过自定义函数操作数据 <!DOCTYPE html> <html lang=" ...

  5. Struts2之i18N国际化

    对于i18n其实没有太多内容,一般的公司用不到这些内容,除非是跨国公司,但即便是跨国公司也不一定会使用i18n来进行国际化处理,所以本篇内容仅供大家了解,不做深入的探讨,希望通过本篇内容,可以帮助大家 ...

  6. webpack快速掌握教程

    转载http://yijiebuyi.com/blog/46fb97b11fb8f4055e0b04d1cecb1f69.html #为什么用webpack 如果我们 前端 javascript 能像 ...

  7. Java界面编程-建立一个可以画出图形的简单框架

    引子:总共使用3个.java文件,建立一个简单界面编程的框架. 第1个文件:NotHelloWorldComponent.java //NotHelloWorldComponent.java 1 im ...

  8. mock.js-无需等待,随机产生数据,让前端独立于后端进行开发

    mock.js所做的 基于 数据模板 生成模拟数据. 基于 HTML模板 生成模拟数据. 拦截并模拟 ajax 请求. Mock.js官方网址:http://mockjs.com/ 1.Mock.js ...

  9. Bootstrap基础学习(一)—表格与按钮

    一.Bootstrap 概述      Bootstrap 是由 Twitter 公司(全球最大的微博)的两名技术工程师研发的一个基于HTML.CSS.JavaScript 的开源框架.该框架代码简洁 ...

  10. 细说OC中的load和initialize方法

    OC中有两个特殊的类方法,分别是load和initialize.本文总结一下这两个方法的区别于联系.使用场景和注意事项.Demo可以在我的Github上找到--load和initialize,如果觉得 ...