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 ...
随机推荐
- 解决mac os下mcss命令报错:env: node\r: No such file or directory
标题无“转载”即原创文章,版权所有.转载请注明来源:http://besteam.im/blogs/article/31/. 我一直对字符界面有抵触感,即使会用vim,我的linux脚本(python ...
- 将spring cloud打包docker镜像
简介:用spring cloud构建微服务后,微服务肯定要docker镜像化然后用rancher等可视化工具管理,这就是走完了一套基本的流程,现在简单介绍下 环境:两台centos7.x的服务器,一台 ...
- Modbus通信协议详解
附:http://www.360doc.com/content/14/0214/13/15800361_352436989.shtml 一.Modbus 协议简介 Modbus 协议是应用于电子控制器 ...
- js精确计算
官方文档:http://mikemcl.github.io/big.js/ 使用方法: x = new Big(0.1); y = x.plus(0.2); // '0.3' var a=Big(0. ...
- 浅谈Java的开放封闭原则
写在前面 最近, 接手了一个新业务,系统的架构可圈可点.但有些地方让人望而生畏,有些代码臃肿难以维护,让人不敢恭维.于是,结合了Java的开放封闭原则,对其中一部分代码进行了重构优化. 先来看下以前系 ...
- 【机器学习】代价函数(cost function)
注:代价函数(有的地方也叫损失函数,Loss Function)在机器学习中的每一种算法中都很重要,因为训练模型的过程就是优化代价函数的过程,代价函数对每个参数的偏导数就是梯度下降中提到的梯度,防止过 ...
- 测试一下js是否可用
昨天刚获批通过了js权限,今天写一段小代码测试下是否可用 我用Javascript添加了 <p> <script type="text/javascript" ...
- 老李分享:天使投资 vs. 风险投资 vs. 私募股权融资
天使投资(Angel Capital) 创意阶段(idea stage)到种子阶段(seed stage) 0 – 1百万美元营业额 还没有盈利 小股东 风险异常的高 不存在负债情况 风险投资(Ven ...
- 1.Maven的安装及配置
1 Maven 介绍 Maven这个词可以翻译为“知识的积累”,也可以翻译为“专家”或“内行”.本书将介绍Maven这一跨平台的项目管理工具.作为Apache组织中的一个颇为成功的开源项目,Maven ...
- filter滤镜的使用
刚开始学css,开始遇到filter不懂什么意思后来到网上查了,觉得解释的很全面,就把它抠下来,以便自己经常来看看. CSS滤镜的使用方法:filter:filtername(parameters) ...