/** 给定⼀个字符串,输出最⻓的回文子串。回⽂串指的是正的读和反的读是⼀样的字符串,例如"aba","ccbbcc"。
* 回文字符,需要判断
* isPalindromic
*/
public class Test05 {
public static void main(String[] args) {
String maxPalindromicStr = "abcccbbccc";
System.out.println("初始字符串:"+ maxPalindromicStr + ", 最长回文字符串:" + getMaxPalindromicStr01(maxPalindromicStr));
System.out.println("初始字符串:"+ maxPalindromicStr + ", 最长回文字符串:" + longestPalindrome(maxPalindromicStr));
}
/**
* 暴力解法, 找出原始字符串的所有字串, 2个指针, 双重移动, for^2
* 对每个一个子串做 回文校验, 与其他回文字串的长度做比较, 记录较大值 for
* s.substring(i, j); 前开后闭
* 保留子串的条件, 一 字串是回文字串, 二 字串的长度要大于最大值
*
* 时间复杂度:两层 for 循环 O(n²),for 循环⾥边判断是否为回⽂,O(n),所以时间复杂度为 O
* (n³)。
* 空间复杂度:O(1),常数个变量。
* @param s
* @return
*/
private static String getMaxPalindromicStr01(String s) {
String ans = "";
int max = 0;
int len = s.length();
for (int i = 0; i < len; i++) {
for (int j = i + 1; j <= len; j++) {
String substring = s.substring(i, j);
if (isPalindromic(substring) && substring.length() > max) {
ans = substring;
max = substring.length();
}
}
}
return ans;
}
/**
* 判断字符串是否是回文子串
* @return
*/
private static boolean isPalindromic(String s) {
int len = s.length(); // 字符串长度
for (int i = 0; i < len/2; i++) {
//游标i 和 len-1- i 处比较, 有对应关系
if (s.charAt(i) != s.charAt(len-1 -i)) {
return false;
}
}
return true;
}
/**
* 扩展中⼼:
* 我们知道回⽂串⼀定是对称的,所以我们可以每次循环选择⼀个中⼼,进⾏左右扩展,判断左右字符是否相
* 等即可。
* 扩展中心右2种选择 一、从⼀个字符开始扩展; 二、从两个字符之间开始扩展, 所以有 n + n-1 个中心
*/
/**
*
* @param s
* @return
*/
public static String longestPalindrome(String s) {
if (s == null || s.length() < 1) {
return "";
}
int start = 0, end = 0;
// 找出最大回文子串的2个下标
for (int i = 0; i < s.length(); i++) {
//扩展中心从一个字符开始
int len1 = expandAroundCenter(s, i, i);
//扩展中心从2个字符中间开始
int len2 = expandAroundCenter(s, i, i + 1);
// 回文的最大长度
int len = Math.max(len1, len2);
// 比较 记录的原始游标位置; 若大 需要更新位置
if (len > end - start) {
start = i - (len - 1) / 2; // 记录了 i变化时 回文字串的前后索引位置
end = i + len / 2;
}
}
return s.substring(start, end + 1); // 前开后闭 找出此最大的回文字符串
}
/**
* 返回回文字符的长度
* @param s 字符串
* @param left 游标初始左位置
* @param right 游标初始右位置
* @return
*/
private static int expandAroundCenter(String s, int left, int right) {
int L = left, R = right;
while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
L--;
R++;
}
return R - L - 1; // 可以获得回文字符的长度
}
}