LeetCode5. Longest Palindromic Substring 最长回文子串 4种方法
题目链接: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种方法的更多相关文章
- 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(最长回文子串, Manacher算法)
Leetcode 5. Longest Palindromic Substring(最长回文子串, Manacher算法) Given a string s, find the longest pal ...
- LeetCode-5:Longest Palindromic Substring(最长回文子字符串)
描述:给一个字符串s,查找它的最长的回文子串.s的长度不超过1000. Input: "babad" Output: "bab" Note: "aba ...
- LeetCode:Longest Palindromic Substring 最长回文子串
题目链接 Given a string S, find the longest palindromic substring in S. You may assume that the maximum ...
- lintcode :Longest Palindromic Substring 最长回文子串
题目 最长回文子串 给出一个字符串(假设长度最长为1000),求出它的最长回文子串,你可以假定只有一个满足条件的最长回文串. 样例 给出字符串 "abcdzdcab",它的最长回文 ...
- [leetcode]5. Longest Palindromic Substring最长回文子串
Given a string s, find the longest palindromic substring in s. You may assume that the maximum lengt ...
- 5. Longest Palindromic Substring(最长回文子串 manacher 算法/ DP动态规划)
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 lengt ...
- 【LeetCode】5. Longest Palindromic Substring 最长回文子串
作者: 负雪明烛 id: fuxuemingzhu 个人博客: http://fuxuemingzhu.cn/ 公众号:负雪明烛 本文关键词:最长回文子串,题解,leetcode, 力扣,python ...
随机推荐
- WebService客户端添加SOAPHeader信息
通过JAXBContext创建Marshaller对头信息进行解析为dom,获取WSBindingProvider,使用Headers.creat()创建soap的Header元素: 另外就是:将us ...
- (转)shell:读取文件的每一行内容并输出
写法一:----------------------------------------------------------------------------#!/bin/bashwhile rea ...
- STM32驱动OV7725摄像头颜色识别
实验目的: 使用stm32驱动OV7725摄像头进行图像实时采集,在tft屏幕上实时显示并识别图像中的特定颜色,在颜色的周围画上框. 实验现象: 我的工程代码链接: http://download.c ...
- js原生的轮播图
<!DOCTYPE html> <html> <head> <meta charset="UTF-8"> <t ...
- XJOI练习2神奇的供水系统
神奇的供水系统 在游遍神秘岛过程中,Z4发现每一个小岛上都有若干个奇怪的类似小水缸似的立方体,这另到Z4相当迷惑不解!这天晚上,忽然下起了一场大雨,在中心岛小树屋上类似那个圆形石槽中间的小孔中涌出了一 ...
- java代码打印打印杨辉三角
郑州大学 徐峰 public class Print { void print(){ int[][] a=new int[6][6]; for(int i=0;i<a.length;i++){ ...
- macos系统下共语言gopath变量的设置
一.问题 在macos下安装golang开发环境,想更改gopath路径,通过export GOPATH=/Volume/E/go 在vscode中通过go env命令查看GOPATH还是原始默认的, ...
- C#调用WebService接口实现天气预报在web前端显示
本文使用web (C#)调用互联网上公开的WebServices接口: (http://www.webxml.com.cn/WebServices/WeatherWebService.asmx)来实现 ...
- C#---------------继承和多态初步
继承:在程序中,如果一个类A:类B,这种机制就是继承. 子类可以继承父类的所有内容(成员)吗? 解析: 1.私有成员(属性和方法) 2.构造函数 3.final修饰过的方法,子类不能进行重写 3.访问 ...
- C#, VB.NET如何将Excel转换为PDF
在日常工作中,我们经常需要把Excel文档转换为PDF文档.你是否在苦恼如何以C#, VB.NET编程的方式将Excel文档转换为PDF文档呢?你是否查阅了许多资料,运用了大量的代码,但转换后的效果依 ...