求最大回文子字符串


题目出处:https://leetcode.com/problems/longest-palindromic-substring/


回文字符串: 简单点说就是字符串反转(reverse)后的结果还是自己。如"abcba", "abccba", 返转后的结果是一样的。最简单的回文字符串是空字符串及长度为1的字符串。

题目要求,给一个字符, 可以假设最大长度的1000.查找最大回文子字符串。并返回一个。


解决方法:

  1. 遍历字符串
  2. 假设当前位置就做为回文字符串的中心。求出其回文字符串的长度。
  3. 与已经查找的最大长度比较,记录两者最大值,作为当前最大长度值。
  4. 直到最后


感想:

以前写过一个实现,今天再看时居然没看懂,只知道大概怎么做的,处理的细节没怎么弄明白。 后面会符上代码,有兴趣的可以研究下微笑

今天决定再写一个版本,思路一样,可代码超简单,也更清晰。

看着原来的代码,想着以前写着肯定很纠结, 这再一次让我明白:大道至简。如果事情太过纠结,那肯定是哪里出问题了!


算法版本:

string longestPalindrome(string s) {
        if(s.length() <= 1)return s;
        int maxLen = 1, start = 0; 
        int index = 0;
        while(index+1 < s.length()){
            //查找第一个不等于当前的字符
            int i = index-1, j = index+1;
            while(s[j]== s[index]) j++;
            index = j;//更新下一次检查的位置
            while(j < s.length() && i >= 0 && s[j]== s[i]){j++; i--;}
            int len = j-i -1;//当前回文长度
            if(len > maxLen){ maxLen = len; start = i+1;}
            //判断后面是否还有没有必要遍历
            if(index + maxLen/2 > s.length())break;
        }
        return s.substr(start, maxLen);
    }


以前的版本

 string longestPalindrome_1(string s) { 
        if(s.length() <= 1) return s;
        int lastMid = 0;
        int lastlen = 0;
        
        int mid = 0;
        int single = 1;
        int length1 = 0;
        int length2 = 0;
        for(int i = 1; i < s.length(); i++){
            // cout<< "  i:" << i << "  item: "<< s[i] << "  mid:" << mid << "  single:" << single  <<endl;
           int oppoIndex = mid - (i - mid);
           
           if((single & 0x01) == 0x01){ //check single
               if(oppoIndex < 0 || s[oppoIndex] != s[i]){
                   single &= 0x02;
                   length1 = (i - mid)*2 -1;
               }
           }
           if((single & 0x02) == 0x02){ //check single = 0x02
                oppoIndex -= 1;
               if(oppoIndex < 0 || s[oppoIndex] != s[i]){
                   single &= 0x01;
                   length2 = (i - mid)*2;
               }
           }
           if(single != 0) continue;
            // cout<< "  length1:" << length1 << "  length2: "<< length2  <<endl;
           int length = length1 > length2 ? length1 : length2;
           length2 = 0;
           length1 = 0;
           //check max
           if(length > lastlen){
               lastlen = length;
               lastMid = mid;
            }
            
            //check single = 0x01
            for(int j = mid+1; j <= i; j++){
                // cout<< "mid: " << mid << "  j: " << j <<endl;
                //check single 1 is ok
                bool ok = true;
                for(int k = 0; k <= i-j; k++){
                    if(s[j-k] != s[j+k]){
                        ok = false;
                        break;
                    }
                }
                if(ok){
                    mid = j;
                    single |= 1;
                }
                //check single 2 is ok
                bool ok1= (s[j] == s[j-1]);
                if(ok1){ 
                    for(int k = 0; k <= i-j; k++){
                        if(s[j-k-1] != s[j+k]){
                            ok1 = false;
                            break;
                        }
                    }
                    if(ok1){
                        mid = j;
                        single |= 0x02; 
                    }
                }
                if(ok || ok1) break;
            }
             
        }
        // cout<< "mid: " << mid << " single:" << single << " len:" << s.length()-mid << endl;
        if((single & 0x01) == 0x01)
            length1 = (s.length()-mid)*2 - 1;
        if((single & 0x02) == 0x02)    
            length2 = (s.length() - mid)*2;
        int length = length1 > length2 ? length1 : length2;
        
        if(length1 > lastlen){
            return s.substr(mid - (s.length()-mid) + 1);
        }
        if(length2 > lastlen){
            return s.substr(mid - (s.length()-mid));
        }
        // cout<< "lastMid: " << lastMid << " lastlen:" << lastlen  << endl;
        
        return s.substr(lastMid-lastlen/2, lastlen);
    }



评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值