跳至主要內容

最长回文子串


最长回文子串

题目

给定一个字符串,找到它最长的回文子字符串(LPS)的长度。在一个回文字符串中,从字符串的末尾向左读和从字符串的开头向右读是一样的。

示例:

输入:"abdbca"
输出:3
解释:最长回文子串是"bdb"

题解

暴力求解

class LPS {

  public int findLPSLength(String st) {
    return findLPSLengthRecursive(st, 0, st.length() - 1);
  }

  private int findLPSLengthRecursive(String st, int startIndex, int endIndex) {
    if (startIndex > endIndex)
      return 0;

    // 每一个只有一个字符的字符串是一个回文
    if (startIndex == endIndex)
      return 1;

    // case 1: 开头和结尾的元素相同
    if (st.charAt(startIndex) == st.charAt(endIndex)) {
      int remainingLength = endIndex - startIndex - 1;
      // 检查剩余的字符串是否是回文子串
      if (remainingLength == findLPSLengthRecursive(st, startIndex + 1, endIndex - 1))
        return remainingLength + 2;
    }

    // case 2: 略过开头或者结尾的一个元素
    int c1 = findLPSLengthRecursive(st, startIndex + 1, endIndex);
    int c2 = findLPSLengthRecursive(st, startIndex, endIndex - 1);
    return Math.max(c1, c2);
  }

  public static void main(String[] args) {
    LPS lps = new LPS();
    System.out.println(lps.findLPSLength("abdbca"));
    System.out.println(lps.findLPSLength("cddpd"));
    System.out.println(lps.findLPSLength("pqr"));
  }
}

自顶向下(备忘录)

class LPS {

  public int findLPSLength(String st) {
    Integer[][] dp = new Integer[st.length()][st.length()];
    return findLPSLengthRecursive(dp, st, 0, st.length() - 1);
  }

  private int findLPSLengthRecursive(Integer[][] dp, String st, int startIndex, int endIndex) {
    if (startIndex > endIndex)
      return 0;

    // 每一个只有一个字符的字符串是一个回文
    if (startIndex == endIndex)
      return 1;

    if (dp[startIndex][endIndex] == null) {
      // case 1: 开头和结尾的元素相同
      if (st.charAt(startIndex) == st.charAt(endIndex)) {
        int remainingLength = endIndex - startIndex - 1;
        // 检查剩余的字符串是否也是一个回文
        if (remainingLength == findLPSLengthRecursive(dp, st, startIndex + 1, endIndex - 1)) {
          dp[startIndex][endIndex] = remainingLength + 2;
          return dp[startIndex][endIndex];
        }
      }

      // case 2: 从开头或者结尾跳过一个字符
      int c1 = findLPSLengthRecursive(dp, st, startIndex + 1, endIndex);
      int c2 = findLPSLengthRecursive(dp, st, startIndex, endIndex - 1);
      dp[startIndex][endIndex] = Math.max(c1, c2);
    }

    return dp[startIndex][endIndex];
  }

  public static void main(String[] args) {
    LPS lps = new LPS();
    System.out.println(lps.findLPSLength("abdbca"));
    System.out.println(lps.findLPSLength("cddpd"));
    System.out.println(lps.findLPSLength("pqr"));
  }
}

自底向上

class LPS {

  public int findLPSLength(String st) {
    // 如果索引i到索引j是一个回文,则dp[i][j]是true。
    // 对于回文序列需要存储回文子序列的长度,而回文子串不用,因为回文子串的长度可以通过endIndex-startIndex+1求出
    boolean[][] dp = new boolean[st.length()][st.length()];

    // 每个只有一个字符的字符串是一个回文
    for (int i = 0; i < st.length(); i++)
      dp[i][i] = true;

    int maxLength = 1;
    for (int startIndex = st.length() - 1; startIndex >= 0; startIndex--) {
      for (int endIndex = startIndex + 1; endIndex < st.length(); endIndex++) {
        if (st.charAt(startIndex) == st.charAt(endIndex)) {
          // 如果它是两个字符 或者 剩余的字符串是一个回文的话
          if (endIndex - startIndex == 1 || dp[startIndex + 1][endIndex - 1]) {
            dp[startIndex][endIndex] = true;
            maxLength = Math.max(maxLength, endIndex - startIndex + 1);
          }
        }
      }
    }

    return maxLength;
  }

  public static void main(String[] args) {
    LPS lps = new LPS();
    System.out.println(lps.findLPSLength("abdbca"));
    System.out.println(lps.findLPSLength("cdpdd"));
    System.out.println(lps.findLPSLength("pqr"));
  }
}
上次编辑于:
贡献者: Neil