每日一题:5. 最长回文子串

97 阅读1分钟

package com.ljp.test.leetcode;

/**

  • 5. 最长回文子串

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

  • 如果字符串的反序与原始字符串相同,则该字符串称为回文字符串。

  • 示例 1:

  • 输入:s = "babad"

  • 输出:"bab"

  • 解释:"aba" 同样是符合题意的答案。

  • 示例 2:

  • 输入:s = "cbbd"

  • 输出:"bb"

  • 提示:

  • 1 <= s.length <= 1000

  • s 仅由数字和英文字母组成

  • 来源:力扣(LeetCode)

  • 链接:5. 最长回文子串

  • 著作权归领扣网络所有。商业转载请联系官方授权,非商业转载请注明出处。 */ public class Number0005 {

    public static void main(String[] args) { String s1 = "babad"; String s2 = "cbbd"; String s3 = "abcddcbaefghjk"; String s4 = "a"; String s5 = "abcd"; System.out.println(DynamicPlanning.longestPalindromicSubstring(s1)); System.out.println(DynamicPlanning.longestPalindromicSubstring(s2)); System.out.println(DynamicPlanning.longestPalindromicSubstring(s3)); System.out.println(DynamicPlanning.longestPalindromicSubstring(s4)); System.out.println(DynamicPlanning.longestPalindromicSubstring(s5)); System.out.println("---------------------------------------------"); System.out.println(ExpandAroundCenter.longestPalindromicSubstring(s1)); System.out.println(ExpandAroundCenter.longestPalindromicSubstring(s2)); System.out.println(ExpandAroundCenter.longestPalindromicSubstring(s3)); System.out.println(ExpandAroundCenter.longestPalindromicSubstring(s4)); System.out.println(ExpandAroundCenter.longestPalindromicSubstring(s5)); }

    /**

    • 动态规划

    • 三大步骤:

    • 1、定义数组元素的含义:result[i][j]=true,表示下标i到下标j是当前字符串的回文子串

    • 2、找出数组元素之间的关系式:result[i+1][j-1]=true and chars[i]==char[j]=true,则result[i][j]=true

    • 3、找出初始值:result[i][i]=true chars[i]==char[i+1],则result[i][i+1]=true chars[i]==char[i+2],则result[i][i+2]=true */ private static class DynamicPlanning {

      public static String longestPalindromicSubstring(String s) { int length = s.length(); if (length == 1) return s; boolean[][] result = new boolean[length][length]; // 最长回文字符串为1 for (int i = 0; i < length; i++) { result[i][i] = true; } char[] chars = s.toCharArray(); int begin = 0, maxLength = 1; // 最长回文字符串为2到length for (int n = 2; n < length; n++) { for (int i = 0; i < length; i++) { int j = i + n - 1; if (j >= length) { break; } if (chars[i] != chars[j]) { result[i][j] = false; } else { // 当子字符串长度为2和3时,必是子回文字符串 if (j - i < 3) { result[i][j] = true; } else { result[i][j] = result[i + 1][j - 1]; } } if (result[i][j] && j - i + 1 > maxLength) { begin = i; maxLength = j - i + 1; } } } return s.substring(begin, begin + maxLength); }

    }

    /**

    • 中心扩展算法 */ private static class ExpandAroundCenter {

      public static String longestPalindromicSubstring(String s) { int length = s.length(); if (length == 1) return s; int begin = 0, maxLength = 1; for (int i = 0; i < length; i++) { int l1 = expandAroundCenter(s, i, i); int l2 = expandAroundCenter(s, i, i + 1); int tempMaxLength = Math.max(l1, l2); if (maxLength < tempMaxLength) { maxLength = tempMaxLength; begin = i - (maxLength - 1) / 2; } } return s.substring(begin, begin + maxLength); }

      private static int expandAroundCenter(String s, int left, int right) { while (left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) { left--; right++; } // left多减了1,right多加了1.所以length=right-left+1-2=right-left-1 return right - left - 1; }

    }

}