【Leetcode】Longest Palindromic Substring Part

问题

Given a string S, find the longest palindromic substring in S. You may assume that the maximum length of S is 1000, and there exists one unique longest palindromic substring.

解法1:

O(N^2) 的算法复杂度的算法就不多说了,无非是遍历I,J,取得一个子串,并对这个字串进行判定,是否是回文串。遍历复杂度为O(N^2),判定复杂度为O(N)(前后指针),所以复杂度为O(N^2).

解法2:

http://leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

根据他的解法,我能够理解他的想法,遍历一遍,取得中数,并向四周扩散,最后得出以此为中数,它最大能够扩充到多大。

当时我就有一个疑问:为什么要加#$^这些符号?

所以我打算不用符号实现一遍他的想法:

class Solution {
public:
    string longestPalindrome(string s) {
        int i =0;
        int C = 0;
        int R = 0;
        int L = 0;
        int i_mirror = 0;
        
        /* init P */
        int *P = new int[s.length()];
        for (i = 0 ; i < s.length(); i++) {
            P[i] = 0;
        }
        
        /* for every charactor */
        for (i = 1 ; i < s.length() - 1; i++) {
            i_mirror = 2*C - i;
            P[i] = R > i ? min(R-i , P[i_mirror]): P[i];
            
            int expand = (P[i] -1)/2;
            while (1 ){
                expand ++;
                int leftExpandIndex = i - expand;
                int rightExpandIndex = i + expand;
                if (leftExpandIndex == 0 || rightExpandIndex == s.length() -1) {
                    expand --;
                    break;
                }
                if (s[leftExpandIndex] != s[rightExpandIndex]) {
                    expand --;
                    break;
                }
                
            }
            P[i] = expand * 2 +1;
            
            if (i + expand > R) {
                C = i;
                L = i - expand;
                R = i + expand;
            }
        }
        
        int maxLen = 0;
        int centelIndex = 0;
        for (i = 0 ; i < s.length(); i++) {
            if(maxLen < P[i])
            {
                centelIndex = i;
                maxLen = P[i];
            }
        }
        int leftPosition = centelIndex - ((maxLen -1)/2);
        return s.substr(leftPosition , maxLen);
        
        
    }

最后我得出来的结论是,奇数回文数能够正确的被解答出来,而偶数的不行。所以在这里我就明白了,他为何要使用特殊符号了。

使用的用意很简单,举个例子:

1. 偶数个回文数:

#a#b#c#c#b#a#

其中以最中间的那个#为中数,左右分别有6个数,正好6 是 abccba 6个数。

2. 奇数个回文数:

#a#b#c#b#a#

其中以c为中数,分别左右有5个数,正好 abcba 也是5个数。


这是一个非常巧妙的解法,当我实现以上的算法的时候,坦白讲我也想再偶数回文数中塞一个数,我相信作者也是通过这个启发到最后他的解法。

修正之后的代码:

string translate(string s)
{
    string rs("^#");
    for (int i = 0; i  < s.length(); i++) {
        rs.push_back(s[i]);
        rs.push_back('#');
    }
    rs.push_back('$');
    //cout<<rs<<endl;
    return rs;
}

class Solution {
public:
    string longestPalindrome(string s) {
        int i =0;
        int C = 0;
        int R = 0;
        int L = 0;
        int i_mirror = 0;
        
        string rs= translate(s);
        
        /* init P */
        int *P = new int[rs.length()];
        for (i = 0 ; i < rs.length(); i++) {
            P[i] = 0;
        }
        
        /* for every charactor */
        for (i = 1 ; i < rs.length() - 1; i++) {
            i_mirror = 2*C - i;
            P[i] = R > i ? min(R-i , P[i_mirror]): 0;
            
            while (rs[i - P[i] -1] == rs[i + P[i] +1] ){
                P[i]++;
            }
            
            if (i + P[i] > R) {
                C = i;
                L = i - P[i];
                R = i + P[i];
            }
        }
        
        int maxLen = 0;
        int centelIndex = 0;
        for (i = 0 ; i < rs.length(); i++) {
            if(maxLen < P[i])
            {
                centelIndex = i;
                maxLen = P[i];
            }
        }
        int leftPosition = (centelIndex - 1 - maxLen)/2;
        //cout<<maxLen<<endl;
        return s.substr(leftPosition , maxLen);
    }
};

分析

分析就不讲了,文中有提到,慢慢看。

总结

有时候需要通过添加某些辅助的数据来帮助自己简化逻辑。在第一个算法中其实可以加入偶数判定,也并非完全不可能实现,比较麻烦而已。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值