(最长连续回文串---一个更容易想到的算法)Longest Palindromic Substring
2017-01-20 10:56
513 查看
关于这道题,我看了国内一些帖子,基本上都是从国外的帖子翻译的,大概有3种算法,动态规划(O(N2)),KMP匹配最长前缀(O(N2))和一个叫做Manacher(O(N))的算法。前两种算法可能比较容易想到,但是不管是复杂度还是编码难度,都不是一个优雅的选择,而第三种算法是一个非普适的算法,如果不事先知道,是几乎不可能在面试中想出来的,而且我认为在最坏情况下其复杂度也不是O(N)。
在这里我提供我的解法,效率不比Manacher差,复杂度为O(kn - k2),其中k为解的长度,在最坏情况下复杂度为O(N2),最好情况下为O(N)。
先贴上我的运行结果
还是比较理想的。
下面说下思路。
我的思路是
1、以整个串的中心为回文串的中心
2、①如果当前中心可以得到的最长回文串小于当前最大值,当前最大值就是答案,结束。②否则,从中心开始向两边迭代比较对称位置上的字符是否相等,记录当前最大值及开始和结束位置索引。③如果迭代结束也没有碰到不相等的字符,说明以当前中心为中心的串就是答案,结束。如果碰到不相等的字符,记录当前最大值和位置信息。
3、将中心位置分别向左、右移动半位(因为中心位置可能不是一个字符而在两个字符之间),跳到第2步。
解释一下,因为题目要求解最长子串,所以不必计算出所有中心的回文串,只要找到最大值就停止。但是如何判断找到最大值呢?考虑一个字符串,可能的最大回文子串就是它自身,以它自身的中点为中点,而这个中点每向左(右)移动半位,新中点可能的最大回文串长度为移动之前的长度减一。
图中黑线为整个字符串的中心,此时可能得到的最长子串的长度就是字符串的长度10。蓝线为向两边移动半位,可能得到的最长子串长度变为9(A到F、B到E),红线为再移动半位,可能得到的最长子串变为8(A到E、C到E)。
所以,我们从整个字符串的中点开始向两边扩展,如果在比较某个中点的对称位置时越过了边界,那么说明这就是最长子串,因为在这之后的所有中点可能的最长子串都不会超过这个值,所以最长子串只可能存在于之前已经比较过的位置,而如果之前有一个更长的子串,那么它一定在之前中点的比较中就已经越过边界并返回了。上图中,以D为中点发现所有边界内的对称位置都相等,那么答案就是7,若中点左移半位,能得到的最长子串也只有6了。而如果一直没有越界,由于在每次比较完毕后都会更新当前最大值,如果在比较某个中点时,发现当前可能的最大值小于当前已记录的最大值,那么当前已记录的最大值就是答案,因为在之后所有的比较中都不会有一个更长的串了。
贴上代码:
在这里我提供我的解法,效率不比Manacher差,复杂度为O(kn - k2),其中k为解的长度,在最坏情况下复杂度为O(N2),最好情况下为O(N)。
先贴上我的运行结果
还是比较理想的。
下面说下思路。
我的思路是
1、以整个串的中心为回文串的中心
2、①如果当前中心可以得到的最长回文串小于当前最大值,当前最大值就是答案,结束。②否则,从中心开始向两边迭代比较对称位置上的字符是否相等,记录当前最大值及开始和结束位置索引。③如果迭代结束也没有碰到不相等的字符,说明以当前中心为中心的串就是答案,结束。如果碰到不相等的字符,记录当前最大值和位置信息。
3、将中心位置分别向左、右移动半位(因为中心位置可能不是一个字符而在两个字符之间),跳到第2步。
解释一下,因为题目要求解最长子串,所以不必计算出所有中心的回文串,只要找到最大值就停止。但是如何判断找到最大值呢?考虑一个字符串,可能的最大回文子串就是它自身,以它自身的中点为中点,而这个中点每向左(右)移动半位,新中点可能的最大回文串长度为移动之前的长度减一。
图中黑线为整个字符串的中心,此时可能得到的最长子串的长度就是字符串的长度10。蓝线为向两边移动半位,可能得到的最长子串长度变为9(A到F、B到E),红线为再移动半位,可能得到的最长子串变为8(A到E、C到E)。
所以,我们从整个字符串的中点开始向两边扩展,如果在比较某个中点的对称位置时越过了边界,那么说明这就是最长子串,因为在这之后的所有中点可能的最长子串都不会超过这个值,所以最长子串只可能存在于之前已经比较过的位置,而如果之前有一个更长的子串,那么它一定在之前中点的比较中就已经越过边界并返回了。上图中,以D为中点发现所有边界内的对称位置都相等,那么答案就是7,若中点左移半位,能得到的最长子串也只有6了。而如果一直没有越界,由于在每次比较完毕后都会更新当前最大值,如果在比较某个中点时,发现当前可能的最大值小于当前已记录的最大值,那么当前已记录的最大值就是答案,因为在之后所有的比较中都不会有一个更长的串了。
贴上代码:
public String longestPalindrome(String s) { char[] input = s.toCharArray(); int length = input.length; int max = 0, left = 0, right = length - 1; // 当前最长回文串的长度和起始、结束位置 boolean odd; // 当前中点为一个字符或在两个字符之间 /** * odd 初始化 */ if (length % 2 == 0) { odd = false; } else { odd = true; } for (int il = length / 2, ir; il >= 0;) { int sl, sr; // 回文串中应该相等的两个字符的索引 ir = length - 1 - il; // 右边中点 int temp = 0; // 以i为中心的串的最大回文数 if (odd) { sl = il - 1; sr = il + 1; temp = 1; //如果是奇数,中点为一个字符,temp初始值为1 } else { sl = il - 1; sr = il; --il; // 如果是偶数,将il左移一位 } if ((sl + 1) * 2 <= max) { return s.substring(left, right + 1); // 如果当前可能的最大值已不可能大于已知的最大值,返回 } // 计算temp while (true) { if (input[sl] == input[sr]) { temp += 2; --sl; ++sr; } else { if(temp > max){ // 如果不相等,更新最大值和相应位置索引 max = temp; left = sl + 1; right = sr - 1; } break; } if (sl == -1 || sr == length) { return s.substring(sl + 1, sr); // 如果sl或sr碰到边界,说明已找到答案,返回 } } if (odd) { sl = ir - 1; sr = ir + 1; temp = 1; } else { sl = ir; sr = ir + 1; temp = 0; ++ir; // 如果是偶数,将ir右移一位 } // 计算temp while (true) { if (input[sl] == input[sr]) { temp += 2; --sl; ++sr; } else { if(temp > max){ // 如果不相等,更新最大值和相应位置索引 max = temp; left = sl + 1; right = sr - 1; } break; } if (sl == -1 || sr == length) { return s.substring(sl + 1, sr); // 如果sl或sr碰到边界,说明已找到答案,返回 } } // 反转odd odd = !odd; } return ""; }
相关文章推荐
- 最长连续回文串(Longest Palindromic Substring)算法探究
- leetcode 5 Longest Palindromic Substring(Manacher算法求最长回文串)
- Longest Palindromic Substring (最长回文串)【面试算法leetcode】
- 最长连续回文串(Longest Palindromic Substring)
- 最长连续回文串(Longest Palindromic Substring)
- 最长连续回文串(Longest Palindromic Substring)
- 【字符串】最长连续回文串(Longest Palindromic Substring)
- 最长连续回文串(Longest Palindromic Substring)
- 最长连续回文串(Longest Palindromic Substring)
- Longest Palindromic Substring 在一个字符串里找最长回文子串@LeetCode
- 动态规划求一个序列的最长回文子序列(Longest Palindromic Substring )
- java常用算法之最长回文子串(Longest Palindromic Substring)
- LeetCode 5. Longest Palindromic Substring(最长回文连续子串)
- 最长回文串:LeetCode:Longest Palindromic Substring
- LeetCode 5:Longest Palindromic Substring(最长回文串)
- 【LeetCode-面试算法经典-Java实现】【005-Longest Palindromic Substring(最长回文子串)】
- LeetCode 5 Longest Palindromic Substring(最长回文子串,暴力剪枝/DP/曼彻斯特算法)
- Longest Palindromic Substring最长回文字符串算法
- 5. Longest Palindromic Substring(最长回文串)
- Longest Palindromic Substring 最长回文串 python实现