对于长度为n的一个字符串A(仅包含数字,大小写英文字母),请设计一个高效算法,计算其中最长回文子串的长度。
数据范围:
要求:空间复杂度
,时间复杂度
进阶: 空间复杂度
,时间复杂度
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
int n = A.length();
int res = 1;
for (int i = 0; i < n; i++) {
int left = i;
int right = i;
while (left >= 0 && right < n) {
if (A.charAt(left) == A.charAt(right)) {
res = Math.max(right - left + 1, res);
left--;
right++;
}else{
break;
}
}
left = i;
right = i + 1;
while (left >= 0 && right < n) {
if (A.charAt(left) == A.charAt(right)) {
res = Math.max(right - left + 1, res);
left--;
right++;
}else{
break;
}
}
}
return res;
}
} public int getLongestPalindrome(String A) {
char[] chars = A.toCharArray();
int l = 1;
for (int i = 0; i < chars.length; i++) {
for (int j = i; j < chars.length; j++) {
if (chars[i] == chars[j]) {
int m = Compare(chars, i, j);
if (l < m) {
l = m;
}
}
}
}
return l;
}
public int Compare(char[] chars1, Integer i, Integer j) {
int n = j - i + 1;
if (n != 1) {
char[] chars2 = new char[n];
System.arraycopy(chars1, i, chars2, 0, n);
for (int o = 0; o < n; o++) {
if (chars2[o] != chars2[n - o - 1]) {
return 1;
}
}
return n;
} else {
return 1;
}
} 该方法思路为。如果字串A[i..j](左闭右闭)为回文串,那么有前提条件:A[(i+1)..(j-1)]为回文串,并且A[i] == A[j]。
时间复杂度:
空间复杂度:
import java.util.*;
public class Solution {
public int getLongestPalindrome (String A) {
int n = A.length();
if (A == null || n < 1) return 0;
boolean[][] dp = new boolean[n][n];
for (int i = 0; i < n; i++) Arrays.fill(dp[i], true);
int maxLen = 1;
for (int i = n-1; i >= 0; i--) {
for (int j = i+1; j < n; j++) {
dp[i][j] = dp[i+1][j-1] & (A.charAt(i) == A.charAt(j));
if (dp[i][j]) {
int len = j - i + 1;
maxLen = len > maxLen ? len : maxLen;
}
}
}
return maxLen;
}
} 我们可以尝试枚举所有回文串的“中心位置”,并向两边进行拓展,直到无法拓展;此时比较回文串长度与已知最大长度。
时间复杂度:
空间复杂度:
import java.util.*;
public class Solution {
public int getLongestPalindrome (String A) {
if (A == null || A.length() < 1) return 0;
int maxLen = 0;
for (int i = 0; i < A.length(); i++) {
int len1 = expandAroundCenter(A, i, i);
int len2 = expandAroundCenter(A, i, i+1);
int len = Math.max(len1, len2);
maxLen = len > maxLen ? len : maxLen;
}
return maxLen;
}
private int expandAroundCenter(String A, int left, int right) {
while (left >= 0 && right < A.length() && A.charAt(left) == A.charAt(right)) {
left -= 1;
right += 1;
}
return right - left - 1;
}
}该算法可以达到时间复杂度,空间复杂度
的进阶要求,但比较复杂。
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
// 填充字符串:123 -> #1#2#3#
// 注意,两边也要有#,这样直接除以2就能返回结果,否则还要分类讨论
StringBuilder sb = new StringBuilder();
for (int i = 0; i < A.length(); i++) {
sb.append('#');
sb.append(A.charAt(i));
}
sb.append('#');
String newS = sb.toString();
// 统计最长回文子串长度
// 基础写法 - 空间复杂度O(1),时间复杂度O(N2);
/*
int max = 0;
for (int i = 0; i < newS.length(); i++) {
int l = i;
int r = i;
int len = 0;
while (l >= 0 && r < newS.length() && newS.charAt(l) == newS.charAt(r)) {
if (newS.charAt(l) != '#') {
if (l == r) {
len++;
} else if (l != r && newS.charAt(l) != '#') {
len += 2;
}
}
l--;
r++;
}
if (len > max) {
max = len;
}
}
*/
// Manacher算法:空间复杂度O(N),时间复杂度O(N)
// 设置一个长度为n的数组:表示以当前元素为中心的回文半径;
int[] lens = new int[newS.length()];
// 设置两个全局的变量:当前最大回文字串的右边界与中心点
// 初始化成-1,表示第一个元素就要外扩
int c = -1;
int b = -1;
int max = 0;
for (int i = 0; i < newS.length(); i++) {
if (i > b) {
// 1.当前元素超出了当前最大回文子串的右边界
// 直接双指针暴力扩
int left = i;
int right = i;
int len = 0;
while (left >= 0 && right < newS.length() && newS.charAt(left) == newS.charAt(right)) {
if (left == right) {
len++;
} else if (left != right) {
len += 2;
}
left--;
right++;
}
if (len > max) {
// 若当前回文子串突破了最大值,则更新c和b
max = len;
c = i;
b = right - 1;
}
// 无论如何,将当前i位置回文子串长度计入lens数组中对应i位置
lens[i] = right - 1 - i;
} else {
// 2.当前元素没有超过当前最大回文子串的右边界
// 必然能找到i相对于c的对称元素iSym,观察iSym的回文子串情况,进行分类讨论
int iSym = c * 2 - i;
int iSymR = lens[iSym];
int bSym = c * 2 - b;
if ((iSym - iSymR) > bSym) {
// 2.1 iSym的回文区域完全包含在bSym...c...b内
// 说明i位置的元素回文子串必然没有突破b的限制,因此不必进行统计,直接沿用iSym的半径和直径,且不必更新c和b;
lens[i] = lens[iSym];
} else if ((iSym - iSymR) < bSym) {
// 2.2 iSym的回文区域超出了bSym...c...b范围
// 说明iSym的回文超出bSym的部分必然没有对应在b处,要不然bSym和b的范围还会再此基础上再扩大,与当前确定的bSym和b范围相冲突,因此不必进行统计,i位置的回文半径就是i到b之间的部分,且不必更新c和b;
lens[i] = b - i;
} else {
// 2.3 i’的回文区域正好达到了bSym之上:
// 说明i到b的部分必然是i位置元素的回文,这部分不必验证,直接验证外面的元素就好,再根据验证的情况决定是否更新c和b:
int right = b + 1;
int left = i * 2 - right;
int len = (b - i) * 2 + 1;
while (left >= 0 && right < newS.length() && newS.charAt(left) == newS.charAt(right)) {
if (left == right) {
len++;
} else if (left != right) {
len += 2;
}
left--;
right++;
}
if (len > max) {
// 若当前回文子串突破了最大值,则更新c和b
max = len;
c = i;
b = right - 1;
}
// 无论如何,将当前i位置回文子串长度计入lens数组中对应i位置
lens[i] = right - 1 - i;
}
}
}
// 记得除以2排除#字符
return max / 2;
}
} public int getLongestPalindrome (String A) {
// write code here
int maxLen=0;
for(int i=0;i<A.length();i++){
int p1=i ,p2=i;
while(p2+1<A.length() && A.charAt(p2)==A.charAt(p2+1)){
p2++;
}
i=p2;
while(p1-1>=0 && p2+1<A.length() && A.charAt(p1-1)==A.charAt(p2+1)){
p1--;
p2++;
}
maxLen=Math.max(maxLen ,p2-p1+1);
}
return maxLen;
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
if (A == null || A.isEmpty()) {
return 0;
}
int len = A.length();
int max = 1;
for (int i = 0; i < len; i++) {
StringBuilder str = new StringBuilder(String.valueOf(A.charAt(i)));
for (int j = i + 1; j < len; j++) {
StringBuilder append = str.append(A.charAt(j));
StringBuilder reverse = new StringBuilder(append);
reverse.reverse();
if (append.toString().contentEquals(reverse)) {
if (append.length() > max) {
max = append.length();
}
}
}
}
return max;
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
int n = A.length();
int max = 1;
for (int i = 0; i < n; i++) {
for (int j = n - 1; j > i ; j--) {
String sub = A.substring(i, j + 1);
StringBuffer a = new StringBuffer(sub).reverse();
if (sub.equals(a.toString())) {
max = Math.max(max, a.length());
}
}
}
return max;
}
} public int getLongestPalindrome(String s) {
StringBuilder sb = new StringBuilder(s);
int n = sb.length();
boolean[][] dp = new boolean[n][n];
int res = 1;
for (int i = 0; i < n; i++) {
dp[i][i] = true;
}
for (int j = 1; j < n; j++) {
for (int i = j - 1; i >= 0; i--) {
if (j - i <= 2 && sb.charAt(i) == sb.charAt(j)) {
dp[i][j] = true;
res = Math.max(res, j - i + 1);
} else if (sb.charAt(i) == sb.charAt(j)) {
dp[i][j] = dp[i + 1][j - 1];
if (dp[i][j]) {
res = Math.max(res, j - i + 1);
}
}
}
}
return res;
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
if (A.length() == 1) return 1;
if (A.isEmpty()) return 0;
int maxCount = 0;
for (int i = 0; i < A.length(); i++) {
int j = 0;
while (j <= i) {
String temp = A.substring(j, A.length() - i + j);
String newTemp = String.valueOf(new StringBuilder(temp).reverse());
if (temp.equals(newTemp) && temp.length() > maxCount) {
return temp.length();
}
j++;
}
}
return 0;
}
} import java.util.Scanner;
// 注意类名必须为 Main, 不要有任何 package xxx 信息
public class Main {
public static void main(String[] args) {
Scanner in = new Scanner(System.in);
// 注意 hasNext 和 hasNextLine 的区别
// while (in.hasNext()) { // 注意 while 处理多个 case
String line = in.nextLine();
int count = getMaxStr(line, 0, line.length() - 1);
System.out.println(count);
// }
}
public static int getMaxStr(String str, int l, int r ) {
if (l == r) {
return 1;
}
if (l == r - 1) {
return str.charAt(l) == str.charAt(r - 1) ? 2 : 1;
}
//决定的有4个方式
int p1 = getMaxStr(str, l + 1, r);
int p2 = getMaxStr(str, l, r - 1);
int p3 = getMaxStr(str, l + 1, r - 1);
int p4 = str.charAt(l) == str.charAt(r) ? 2 : 0 ;
if (p4 != 0) {
p4 = p4 + getMaxStr(str, l + 1, r - 1);
}
return Math.max(p1, Math.max(p2, Math.max(p3, p4)));
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
String B = new StringBuffer(A).reverse().toString();
int[][] dp = new int[A.length() + 1][A.length() + 1];
for (int i = 1; i <= A.length(); i++)
for (int j = 1; j <= A.length(); j++){
if (A.charAt(i - 1) == B.charAt(j - 1))
dp[i][j] = dp[i - 1][j - 1] + 1;
}
int[] len = new int[dp.length];
for (int i = 0; i < dp.length; i++) {
int max = Arrays.stream(dp[i]).max().getAsInt();
len[i] = max;
}
return Arrays.stream(len).max().getAsInt();
}
} import java.util.*;
public class Solution {
public int getLongestPalindrome (String A) {
// write code here
int maxlen = 1;
int n = A.length();
boolean[][] dp = new boolean[n][n];
for(int right = 1; right < n; right++){
for(int left = 0; left <= right; left++){
//两端字符不相同,必定不是回文,直接略过
if(A.charAt(left) != A.charAt(right))
continue;
//当窗口内只有1个字符或两个字符时候,一定是回文。如:"a", "aa", 其实这里相当于起始条件。
if(right-left<=1){
dp[left][right] = true;
}else{
dp[left][right] = dp[left+1][right-1];
}
if(dp[left][right] && right-left+1>maxlen){
maxlen = right-left+1;
}
}
}
return maxlen;
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
String reverse = new StringBuilder(A).reverse().toString();
int result = 0;
for (int i = 0; i < A.length(); i++) {
if (result > A.length() - i) {
break;
}
for (int j = i + 1 + result; j <= A.length(); j++) {
String substring = A.substring(i, j);
if (reverse.contains(substring)) {
// 求出公共子串
if (reverse.substring(reverse.length() - j,
reverse.length() - i).equals(substring)) {
// 如果位置满足回文串的相关性,那么就是回文串没错了
result = substring.length();
}
} else {
break;
}
}
}
return result;
}
} import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
// write code here
int length = A.length();
int count = length > 0 ? 1 : 0;
for (int i = 0 ; i < length - 1; i++) {
char c = A.charAt(i);
int d = find(i, -1, length, A);
if (count < d) {
count = d;
}
if (c == A.charAt(i + 1)) {
d = find(i, i + 1, length, A);
if (count < d) {
count = d;
}
}
}
return count;
}
public int find(int i, int y, int length, String A) {
int count = 0;
int j = i - 1;
int k = y == -1 ? i + 1 : y + 1;
if (j < 0 || k >= length) {
return y - i + 1;
}
for (; j >= 0 && k <= length - 1; j--, k++) {
char c1 = A.charAt(j);
char c2 = A.charAt(k);
if (c1 != c2) break;
}
if (count < k - j - 1) {
count = k - j - 1;
}
return count;
}
} public int getLongestPalindrome (String A) {
if(A==null){
return 0;
}
if(A.length()<2){
return A.length();
}
int ans=1;
for(int i=0;i<A.length();i++){
for(int j=i+1;j<A.length();j++){
String str=A.substring(i,j+1);
if(str.equals(new StringBuilder(str).reverse().toString())){
ans=Math.max(ans,str.length());
}
}
}
return ans;
} 可能我只会简单粗暴的方法
import java.util.*;
public class Solution {
/**
* 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
*
*
* @param A string字符串
* @return int整型
*/
public int getLongestPalindrome (String A) {
if (A.length() <= 1) {
return A.length();
}
int max = 1;
for (int i = 0; i < A.length(); i++) {
for (int j = i + 1; j < A.length(); j++) {
String substring = A.substring(i, j + 1);
if (substring.equals(new StringBuilder(substring).reverse().toString())) {
max = Math.max(max, substring.length());
}
}
}
return max;
}
}