[LeetCode] 5. 最长回文子串

好难呜呜呜呜

方法一:动态规划

class Solution {
public String longestPalindrome(String s) {
    if(s.equals("")) return "";
        String origin=s;
        String reverse=new StringBuffer(s).reverse().toString();
        int length=s.length();
        int[][] arr=new int[length][length];
        int maxLen=0;
        int maxEnd=0;
        for(int i=0;i<length;i++){
            for(int j=0;j<length;j++){
                if(origin.charAt(i)==reverse.charAt(j)){
                    if(i==0||j==0){
                        arr[i][j]=1;
                    }else{
                        arr[i][j]=arr[i - 1][j - 1] + 1;
                    }
                }
            /**********修改的地方*******************/
            if(arr[i][j]>maxLen){
                int beforeRev=length-j-1;
                if (beforeRev + arr[i][j] - 1 == i) { //判断下标是否对应
                    maxLen = arr[i][j];
                    maxEnd = i;
                }
            }
        }
        }
    //return s.substring(maxEnd - maxLen + 1, maxEnd + 1);
    return s.substring(maxEnd-maxLen+1,maxEnd+1);
}
}

 

 方法二:相比于方法一 对arr数组进行了优化,把二维降为一维

class Solution {
public String longestPalindrome(String s) {
    if(s.equals("")) return "";
        String origin=s;
        String reverse=new StringBuffer(s).reverse().toString();
        int length=s.length();
        int[]arr=new int[length];
        int maxLen=0;
        int maxEnd=0;
        for(int i=0;i<length;i++){
            for(int j=length-1;j>=0;j--){
                if(origin.charAt(i)==reverse.charAt(j)){
                    if(i==0||j==0){
                        arr[j]=1;
                    }else{
                        arr[j]=arr[j - 1] + 1;
                    }
                }else{
                    arr[j]=0;
                }
                if(arr[j]>maxLen){
                    int beforeRev=length-j-1;
                    if (beforeRev + arr[j] - 1 == i) { //判断下标是否对应
                        maxLen = arr[j];
                        maxEnd = i;
                    }
                }
            }
        }
    return s.substring(maxEnd-maxLen+1,maxEnd+1);
}
}

 没有什么实质性的提高哈。

liweiwei1419 给出的动态规划的答案
public class Solution {

    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }

        boolean[][] dp = new boolean[len][len];
        for (int i = 0; i < len; i++) {
            Arrays.fill(dp[i], false);
        }
        // 初始化
        for (int i = 0; i < len; i++) {
            dp[i][i] = true;
        }

        char[] charArray = s.toCharArray();
        int maxLen = 1;
        int start = 0;

        for (int j = 1; j < len; j++) {
            for (int i = 0; i < j; i++) {

                dp[i][j] = charArray[i] == charArray[j] && (j - i < 3 || dp[i + 1][j - 1]);

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

方法三:中心扩散

public class Solution {

    public String longestPalindrome(String s) {
        int len = s.length();
        if (len < 2) {
            return s;
        }
        int maxLen = 1;
        String res = s.substring(0, 1);
        // 中心位置枚举到 len - 2 即可
        for (int i = 0; i < len - 1; i++) {
            String oddStr = centerSpread(s, i, i);
            String evenStr = centerSpread(s, i, i + 1);
            String maxLenStr = oddStr.length() > evenStr.length() ? oddStr : evenStr;
            if (maxLenStr.length() > maxLen) {
                maxLen = maxLenStr.length();
                res = maxLenStr;
            }
        }
        return res;
    }

    private String centerSpread(String s, int left, int right) {
        // left = right 的时候,此时回文中心是一个字符,回文串的长度是奇数
        // right = left + 1 的时候,此时回文中心是一个空隙,回文串的长度是偶数
        int len = s.length();
        int i = left;
        int j = right;
        while (i >= 0 && j < len) {
            if (s.charAt(i) == s.charAt(j)) {
                i--;
                j++;
            } else {
                break;
            }
        }
        // 这里要小心,跳出 while 循环时,恰好满足 s.charAt(i) != s.charAt(j),因此不能取 i,不能取 j
        return s.substring(i + 1, j);
    }
}

 

posted @ 2020-05-08 20:44  doyi  阅读(142)  评论(0编辑  收藏  举报