字符串算法系列-LeetCode#5.LongestPalindromicSubstring

  • 题目:给定一个字符串,找到该字符串的最长回文子串(连续)
    例如:“babad”的最长回文子串为“bad”或“aba”

  • 思路一(中心扩展法):
    第一种情况:回文子串可以看做由第i个元素想左右两侧扩散,如果左右两侧元素相同,则继续向左右两侧扩散(这样求的回文子串是奇数个元素);
    第二种情况:比较第i个、第i+1个元素大小,相同则继续向左右扩散(得到的是偶数回文)
    定义一个result来记录当前最长回文,定义start,end两个指针

  • 代码:
public class Solution {
    public String longestPalindrome(String s) {
        if(s == null || s.length() == 1){
            return s;
        }
        int len = s.length();
        String result = "";
        int start = 0;
        int end = 0;
        //遍历s中的每个元素,求回文
        for(int i = 0; i < len; i++){
            //首先求奇数个数的回文,以第i个元素为中心
            start = i-1;
            end = i+1;
            while( start >= 0 && end < len && s.charAt(start) == s.charAt(end)){
                start--;
                end++;
            }
            if(end - start -1 > result.length()){
                result = s.substring(start+1, end);
            }

           //求偶数个数的回文,以第i和第i+1个元素比较
            start = i;
            end = i+1;
            while(start >= 0 && end < len && s.charAt(start) == s.charAt(end)){
                start--;
                end++;
            }
            if(end - start -1 > result.length()){
                result = s.substring(start+1, end);
            }
        }
        return result;
    }
}
  • 值得注意的点:

    * String类的substring()方法,第二个"s"也是小写;
    * substring(begin,end)方法截取字符串时,是取[begin,end)中间的字符,也就是说包括头不包括尾
    
    * while循环求回文时,一定要加上是否start、end两个指针是否越界的判断
    * 在求回文长度时,最好在纸上比划比划,确定长度是end-(start+1)
    

  • 思路二:遍历字符串,同样定义两个指针left和right,left指针指向拓展的起始位置,遇到相同元素,则下次遍历的起始位置需要跳过这些相同的元素(因为从中间的相同元素开始拓展肯定没有从第一个得到的回文长)
public class Solution {
    public String longestPalindrome(String s) {
        if(s.length() == 0 || s.length() == 1 || s == null){
            return s;
        }
        int start = 0;
        int maxLen = 1;//每个字符自己是一个回文
        //遍历字符串,以i为起始点
        for(int i = 0; i < s.length();){
            //字符串的长度减去遍历起点位置小于当前最长回文长度的一半,则可以退出循环了
            if(s.length() - i <= maxLen/2){
                break;
            }
            int left = i;
            int right = i;
            //相同的字符作为回文,right指针右移
            while(right < s.length()-1 && s.charAt(right) == s.charAt(right+1)){
                right++;
            }
            //相同的字符可以直接跳过,无需向两边拓展
            i = right+1;
            while(left > 0 && right < s.length()-1 && s.charAt(left-1) == s.charAt(right+1)){
                left--;
                right++;
            }
            if(right-left+1 > maxLen){
                maxLen = right-left+1;
                start = left;
            }
        }
        return s.substring(start,start+maxLen);
    }
}

思路二:首先在每两个相邻字符中间插入一个分隔符,当然这个分隔符要在原串中没有出现过。一般可以用’#’分隔。这样就非常巧妙的将奇数长度回文串与偶数长度回文串统一起来考虑了。(Manacher算法,时间复杂度为o(n))待学习研究

更多解法思路(动态规划+暴力+Manacher)
http://www.cnblogs.com/leoin2012/p/3984997.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值