您的位置:首页 > 其它

leetcode解题报告5. Longest Palindromic Substring

2017-03-18 16:47 162 查看

leetcode解题报告5. Longest Palindromic Substring

题目地址

难度是medium

题目描述

回文串:当一个字符串从左到右,和从右到左是一样的的时候,称为回文串

题目要求,给定一个字符串,找出它的子串里面最长的回文串

我的思路

第一个思路:首先最直观的思路是暴力求解,遍历所有子串,判断是否是回文串,在选择最长的那个就行了。简单可行,但肯定超时

第二个思路:通过窗口移动来遍历子串,窗口大小从大到小,那么这样找到第一个子串如果是回文串,那肯定是最长回文串了,不用全部遍历。但这只是比暴力方法稍微好一点,当最长回文串长的时候,优化明显,但当最长回文串短时,几乎和暴力方法无异。我尝试实现,并提交,果然结果超时。当多提交几次,发现有时又能AC,可能这个办法超时不是很严重。

第三个思路:根据回文串的特点,可以通过选定一个位置,然后左右延拓的办法来遍历子串。遍历奇数长度的子串,对某个位置的字符为中心,第一个子串是中心本身,左右长度加一,遇到不是回文串时(或超过字符串范围时),结束以该中心的子串寻找。选择下一个中心,继续。遍历偶数长度的子串类似,只是以某两个相邻的字符为中心。这方法相比暴力少遍历很多子串。利用回文串的特点,当一个子串不是回文串时,那么它左右延拓得到的字符串也肯定不是回文串。我们就能跳过遍历这些回文串。而且判断某个子串是否回文串时,我们只是判断左右延拓的字符是否相等而已,相比暴力遍历时要好很多。

我的代码

class Solution {
public:
string longestPalindrome(string s) {
string ans;
int max = 0;
int len;
//遍历奇数长度的子串
for (int i = 0; i < s.size(); i++) {
len = 1;
int a = i - 1;
int b = i + 1;
while (a >= 0 && b < s.size()) {
if (s[a] != s) {

4000
break;
}
a--;
b++;
len += 2;
}
if (len > max) {
ans = s.substr(a+1, len);
max = len;
}
}
//遍历偶数长度的子串
for (int i = 0; i < s.size(); i++) {
len = 0;
int a = i;
int b = i+1;
while (a >= 0 && b < s.size()) {
if (s[a] != s[b]) {
break;
}
a--;
b++;
len += 2;
}
if (len > max) {
ans = s.substr(a+1, len);
max = len;
}
}

return ans;
}
};


[b]阅读官方题解

题目地址

情况总结如下,具体看官方题解

第一个办法是比较粗糙的。具体是找原字符串和它逆序字符串之间的公共子串。这个公共子串是回文串的一个超集,所以还得判断是否是回文串。

第二个办法,暴力遍历,超时,没什么可说的

第三个办法是动态规范。比较直观。

第四个办法就是和我的第三个思路是一致的。

第五个办法是Manacher’s algorithm。比较复杂。

思想核心总结

对于字符串问题,最直观的思路是暴力遍历。但这一般是不好的。我们希望不是简单地遍历,而是能利用问题的特性和后面遍历能利用到前面遍历的信息,避免不必要的遍历,从而加速。

一般来说,暴力遍历的下一步思路是考虑动态规划或窗口移动等方法,加速遍历。

在有些时候,更应该利用题目的特性来优化,比如本题目的回文串的特点。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: