LeetCode解题笔记 3 —— 5.最长回文子串

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/m940034240/article/details/88839328

tips:回文的意思是正着念和倒着念一样,如:上海自来水来自海上

问题

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

解法

暴力解法:

class Solution {
    public String longestPalindrome(String s) {
        int length = s.length();
        if(s.length() < 2){
            return s;
        }
        int left=0; //当前最长回文子串的左下标
        int right=0;//当前最长回文子串的右下标
        int max = 1;//当前最长回文子串的长度
        for(int i = 0 ; i < length; i++){
            String str = s.substring(i,length);
            int l2 = str.length();
            if(l2<=max) break; //剩余长度小于当前最长回文子串的长度,结束校验
            for(int j = 0; j < l2; j++){
                if(j + 1<=max) continue;
                String msg = str.substring(0,j+1);
                boolean flag = true;//是否为回文字符串标识
                int l3 = msg.length();
                int size = l3/2;
                for(int k = 0; k < size; k++){
                    if(msg.charAt(k)!=msg.charAt(l3-1-k)){
                        flag = false;
                        break;
                    }
                }
                if(flag){
                    if(l3>max){
                        max = l3;
                        left = i ;
                        right = i + j;
                    }
                }
            }
        }
        return s.substring(left, right + 1);
    }
}

将所有可能截取到的字符串都判断一下是否为回文字符串,并选出最长的一种,这种解法结果虽然是正确的,但运行时间过长,占用内存过多,在LeetCode提交时有概率提示超时,故需进行优化

优化解法:

class Solution {
    public String longestPalindrome(String s) {
        int length = s.length();
        if(s.length() < 2){
            return s;
        }
        int left=0; //当前最长回文子串的左下标
        int right=0;//当前最长回文子串的右下标
        int max = 1;//当前最长回文子串的长度
        
        
        int indexL,indexR;//中间部分字母连续相同的左右下标
        
        for(int i=0; i < length; i++){
            char c = s.charAt(i);
            indexL = i;
            indexR = i;
            //先获取连续相同字符的左下标
            for(int k = 1; k <= i; k++){
                if(s.charAt(i-k)!=c){
                    indexL = i - k + 1;
                    break;
                }else if(k == i){
                    indexL = i - k;
                }
            }
            //获取连续相同字符的右下标
            for(int k = 1; k <= length - 1 - i; k++){
                if(s.charAt(i+k)!=c){
                    indexR = i + k - 1;
                    break;
                }else if(k == length - 1 - i){
                    indexR = i + k;
                }
            }
            int z = indexR - indexL + 1;
            if(z>max){
                max = z;
                left = indexL;
                right = indexR;
            }
            //然后依次判断左右两边的字符是否相同,直到出现不同或超出范围为止
            for(int k = 1; k <= indexL; k++){
                if(indexL- k<0 || indexR+k>=length) break;
                char leftC = s.charAt(indexL- k);
                char rightC = s.charAt(indexR + k);
                if(leftC!=rightC){
                    int t = indexR + k - 1 - (indexL - k + 1) + 1;
                    if(max < t){
                        max = t;
                        left = indexL - k + 1;
                        right = indexR + k - 1;
                    }
                    break;
                }else if(indexL - k == 0 || indexR + k == length-1){
                    int t = indexR + k - (indexL - k) + 1;
                    if(max < t){
                        max = t;
                        left = indexL - k;
                        right = indexR + k;
                    }
                    break;
                }
            }
        }
        return s.substring(left, right + 1);
    }
}

优化后效果

猜你喜欢

转载自blog.csdn.net/m940034240/article/details/88839328