Leetcode第5题 最长回文子串
题目描述
https://leetcode.cn/problems/longest-palindromic-substring/
给你一个字符串 s,找到 s 中最长的回文子串。
如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。
个人思路
首先判断写一个判断回文的函数,然后从中间开始向左或者向右遍历判断下一个字符是否为回文(即[0,n-2]相当于中心点向左偏移),如果为回文则直接返回,因为中间的回文最长。
    public String judge(String s){
        if(s.length()<=1)return s;
        if(s.length()==2)return s.charAt(0)==s.charAt(1)?s:String.valueOf(s.charAt(0));
        int i=s.length()/2;
        int j=0;
        StringBuilder stringBuilder=new StringBuilder("");
        if(i%2==0){
            while (i>0 && i-j-1 >=0  && i+j<=s.length()){
                if(s.charAt(i+j)==s.charAt(i-j-1)){
                    stringBuilder.append(s.charAt(i-j));
                    j++;
                }else {
                    break;
                }
            }
        }else {
            while (i>0 && i-j >=0  && i+j<=s.length()){
                if(s.charAt(i-j)==s.charAt(i+j)){
                    stringBuilder.append(s.charAt(i-j));
                    j++;
                }else {
                    break;
                }
            }
        }
        StringBuilder x=new StringBuilder("");
        for(int l=1;l<stringBuilder.length();l++){
            x.append(stringBuilder.charAt(l));
        }
        if(s.length()%2==0){
            x.append(stringBuilder.charAt(0));
        }
        x.append(stringBuilder);
        return x.toString();
    }
    public String longestPalindrome(String s) {
        if(s.length()<=1)return s;
        if(s.length()==2)return s.charAt(0)==s.charAt(1)?s:String.valueOf(s.charAt(0));
        int i=s.length()/2;
        int sum=0;
        String s1="";
        String temp=judge(s);
        if(temp.length()>sum){
            sum=temp.length();
            s1=temp;
        }
        for(int j=0;j<s.length()/2;j++){
            //        left
            temp = s.substring(j*2,s.length());
            temp =judge(temp);
            if(temp.length()>sum){
                sum=temp.length();
                s1=temp;
            }
            //        right
            temp=s.substring(0,s.length()-j*2);
            temp =judge(temp);
            if(temp.length()>=sum){
                sum=temp.length();
                s1=temp;
            }
        }
        temp=s.substring(0,2);
        temp = judge(temp);
        if(temp.length()>sum){
            sum=temp.length();
            s1=temp;
        }
        temp=s.substring(s.length()-2);
        temp = judge(temp);
        if(temp.length()>sum){
            sum=temp.length();
            s1=temp;
        }
        return  s1;
    }代码优化
原代码思路特别长,为此做出优化。
判断回文的方式进行修改,返回变成下标,而不是直接返回回文字符,方便判断
public int expandAroundCenter(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { --left; ++right; } return right - left - 1; }弃用改变中心点的位置,直接改左右字符串开始的位置
public String longestPalindrome(String s) { if (s == null || s.length() < 1) { return ""; } int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); int len2 = expandAroundCenter(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); }其他方法
动态规划
dp[i][j]表示从i到j是一个回文,如果dp[i][j]要是回文,则需要s[i]==s[j],并且dp[i][j]=dp[i+1,j-1],如图所示。

public class Solution { public String longestPalindrome(String s) { if (s.length() < 2) return s; int maxLen = 1; int begin = 0; // dp[i][j] 表示 s[i, j] 是否是回文串 boolean[][] dp = new boolean[len][len]; // 使用将字符串传为字符数组,使得每次不需要进行chatAt() char[] charArray = s.toCharArray(); for (int i = 0; i < len; i++) { dp[i][i] = true; } for (int j = 1; j < len; j++) { for (int i = 0; i < j; i++) { if (charArray[i] != charArray[j]) { dp[i][j] = false; } else { // 长度为3,两边相同即回文 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); } }