[Leetcode]5. 最长回文子串

题目描述

给你一个字符串 s,找到 s 中最长的回文子串。

  • 示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
  • 示例 2:
输入:s = "cbbd"
输出:"bb"
  • 示例 3:
输入:s = "a"
输出:"a"
  • 示例 4:
输入:s = "ac"
输出:"a"

第一种解法(暴力解法)

class Solution {

  //查询指定字符串最长子串
  public String longestPalindrome(String s) {
    int maxLen = 0;
    int left = 0;
    //babad
    for (int i = 0; i < s.length(); i++) {
      for (int j = i; j < s.length(); j++) {
        String temp = s.substring(i, j + 1);
        if ((j - i + 1) > maxLen && isPalindrome(temp)) {
          maxLen = j - i + 1;
          left = i;
        }
      }
    }
    return s.substring(left, maxLen + left);
  }

  private boolean isPalindrome(String source) {
    char[] array = source.toCharArray();
    int left = 0;
    int right = array.length - 1;
    while (left < right) {
      if (array[left] != array[right]) {
        return false;
      }
      left++;
      right--;
    }
    return true;
  }

  public static void main(String[] args) {
    System.out.println(new Solution().longestPalindrome("a"));
  }
}

找出所有子串,判断每一个子串是否是回文串。时间复杂度为 O(N^3),超出时间限制。

第二种解法(中心扩展)

class Solution2 {

  //查询指定字符串最长子串
  public String longestPalindrome(String s) {
    //babad
    int[] res = new int[2];
    for (int i = 0; i < s.length(); i++) {
      searchPalindrome(s, i, i, res);
      searchPalindrome(s, i, i + 1, res);
    }
    return s.substring(res[0], res[0] + res[1]);
  }

  private void searchPalindrome(String s, int start, int end, int[] res) {
    while (start >= 0 && end < s.length()) {
      if (s.charAt(start) != s.charAt(end)) {
        break;
      }
      start--;
      end++;
    }
    if (end - start - 1 > res[1]) {
      res[0] = start + 1;
      res[1] = end - start - 1;
    }
  }

  public static void main(String[] args) {
    System.out.println(new Solution2().longestPalindrome("a"));
  }
}

从一个中心向两边扩展,直到可以判断出不是回文串,例如 habcdcbag ,以d为中心扩展,得到的回文串为 abcdcba,从所有回文串中选出最大的。时间复杂度为 O(N^2),可以通过AC。

第三种解法(动态规划)

class Solution3 {

  //查询指定字符串最长子串
  public String longestPalindrome(String s) {
    int len = s.length();
    if (len < 2) {
      return s;
    }
    int maxLen = 1;
    int start = 0;
    //memo[j][i]表示下标j-i之间为回文串
    boolean[][] memo = new boolean[len][len];
    for (int i = 0; i < len; i++) {
      memo[i][i] = true;
    }
    for (int i = 0; i < len; i++) {
      for (int j = 0; j < i; j++) {
        if (s.charAt(i) != s.charAt(j)) {
          memo[j][i] = false;
        } else {
          //[0,2]
          if (i - j < 3) {
            memo[j][i] = true;
          } else {
            memo[j][i] = memo[j + 1][i - 1];
          }
        }
        if (memo[j][i] && i - j + 1 > maxLen) {
          maxLen = i - j + 1;
          start = j;
        }
      }
    }
    return s.substring(start, start + maxLen);
  }

  public static void main(String[] args) {
    System.out.println(new Solution3().longestPalindrome("abcbads"));
  }
}

如果一个子串的头尾不相同,一定不是回文串,
如果相等,判断去除头尾之后的子串是否为回文串。
以 habcdcbag 字符串为例,habcdcba 不是回文子串,abcdcba 是回文子串。时间复杂度为 O(N^2),可以通过AC。

posted @ 2021-02-25 22:41  strongmore  阅读(47)  评论(0编辑  收藏  举报