5.最长回文子串(过程分析)

//中心扩散法,从中间向两边扩散。比动态规划计算量更少。
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len < 2){
            return s;
        }

        int maxLen = 1;
        int begin = 0;

        char[] charArray = s.toCharArray();
        for(int i = 0; i < len - 1; i++){
            int oddLen = expandAroundCenter(charArray,i,i);
            int evenLen = expandAroundCenter(charArray,i, i + 1);

            int curMaxLen = Math.max(oddLen, evenLen);
            if(curMaxLen > maxLen){
                maxLen = curMaxLen;
                //这一步需要自己去发现规律 
                //比如 b a b a b 中的 b a b, i = 1 maxLen= 3 begin = 0 和 
                //b a a b 中的b a a b,i = 1 maxLen = 4 begin = 0 就可归纳得出规律
                begin = i - (maxLen - 1) / 2;
            }
        }
        return s.substring(begin, begin + maxLen);
    }

    private int expandAroundCenter(char[] charArray, int left, int right){
        //当left = right 的时候, 回文中心是一个字符,回文串的长度是奇数
        //当 right = left + 1的时候,此时回文中心两个字符,回文串的长度是偶数
        int len = charArray.length;
        int i = left;
        int j = right;
        while(i>=0 && j < len){
            if(charArray[i] == charArray[j]){
                i--;
                j++;
            } else{
                break;
            }
        }
        //回文串的长度是j - i + 1 - 2 = j - i + 1 这个2是i-- 和j++多出来的2
        return j - i - 1;
    }
}

题解过程:
b  a  b  a  b
0  1  2  3  4

首先 0 0 和 0 1 开始 => 0 0 判断相等退出,返回 1 - (-1) - 1 = 1 同理 0 1直接退出,返回 0
其次 1 1 和 1 2 开始 => 1 1 判断相等后扩散 0 2 也相等,返回 3 。同理 1 2返回 0。
其余都类似
最终得到 bab为最长子串,长度为3。

时间复杂度:O(n2)
空间复杂度:O(n2)


//动态规划 => 通过把原问题分解为相对简单的子问题的方式求解复杂问题的方法。动态规划常常适用于有重叠子问题和最优子结构性质的问题。
class Solution {
    public String longestPalindrome(String s) {
        int len = s.length();
        if(len < 2){
            return s;
        }

        int maxLen = 1;
        int begin = 0;

        //dp[i][j] 表示 s[i..j] 是否是回文串
        boolean[][] dp = new boolean[len][len];

        //自己对应的一个字母肯定是回文串
        for(int i = 0; i < len; i++){
            dp[i][i] = true;
        }

        char[] charArray = s.toCharArray();
        //左下角先填 [0 1] [0 2] [1 2] [0 3] [1 3] [2 3] [....] 竖着先填
        for(int j = 1; j < len; j++){
            for(int i = 0; i < j; i++){ 
                if(charArray[i] != charArray[j]){
                    dp[i][j] = false;
                } else {
                    if(j - i < 3){
                        dp[i][j] = true;
                    }else {
                        dp[i][j] = dp[i + 1][j - 1];
                    }
                }

                //只要 dp[i][j] == true 成立, 就表示字串 s[i .. j] 是回文,此时记录回文长度和起始位置
                if(dp[i][j] && j - i + 1 > maxLen){
                    maxLen = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + maxLen);
    }
}

题解过程:
b  a  b  a  b
0  1  2  3  4


首先每一个[i, i]都为true。
   0 1 2 3 4
0  T
1    T
2      T
3        T
4          T

对于[0, 1] => [i] != [j], 对于[0, 2] 有 [i] = [j] 且 j - i < 3。其他同理
   0 1 2 3 4
0  T F T F
1    T F T F
2      T F T
3        T F
4          T

对于 [0, 4] 则需要用到动态规划, 利用前面的已知信息。首先可知[0] = [4], 且[1,3]为T, 故为T。
   0 1 2 3 4
0  T F T F T
1    T F T F
2      T F T
3        T F
4          T

左下角为对称, 最终可得到最大字串。

时间复杂度:O(n2)
空间复杂度:O(n2)

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值