给定一个字符串s,找到s中最长的回文子串。你可以假设s的最大长度为1000.
这题是很经典的题目,找到最长回文子串,回文就是bab,cabac这样的。
题解
解法一
暴力法,列举所有的子串,判断是否为回文串,很明显时间复杂度为O(n^2)。
解法二
将原字符串s倒置s',然后寻找最长回文串就变成寻找字符串s和s'的最长公共子串,需要注意的一点,找到最长公共子串后,还需要判断子串是否是回文。
解法三,动态规划
很多时候关于字符串的判断,需要用到动态规划的思想。
我们判断i到j的子串为回文串时,等价于i+1到j-1时回文串&&Si=Sj。时间复杂度仍为O(n^2),空间复杂度也是。
代码
public String longestPalindrome(String s) { int length = s.length(); boolean[][] P = new boolean[length][length]; int maxLen = 0; String maxPal = ""; for (int len = 1; len <= length; len++) //遍历所有的长度 for (int start = 0; start < length; start++) { int end = start + len - 1; if (end >= length) //下标已经越界,结束本次循环 break; P[start][end] = (len == 1 || len == 2 || P[start + 1][end - 1]) && s.charAt(start) == s.charAt(end); //长度为 1 和 2 的单独判断下 if (P[start][end] && len > maxLen) { maxPal = s.substring(start, end + 1); } } return maxPal; }
解法四,扩展中心
每次循环选择一个中心,进行左右扩展,判断左右字符是否相等即可。
因为存在奇数和偶数的字符串,所有共有n+n-1个中心.
public String longestPalindrome(String s) { if (s == null || s.length() < 1) return ""; int start = 0, end = 0; for (int i = 0; i < s.length(); i++) { int len1 = expandAroundCenter(s, i, i); int len2 = expandAroundCenter(s, i, i + 1); int len = Math.max(len1, len2); if (len > end - start) { start = i - (len - 1) / 2; end = i + len / 2; } } return s.substring(start, end + 1); } private 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; }
我的解法代码
import java.util.HashMap; import java.util.Map; import java.util.Scanner; public class leetcode { public static void main(String[] args) { Scanner scan = new Scanner(System.in); String s = scan.nextLine(); String str = longestPalindrome(s); System.out.println(str); } public static String longestPalindrome(String s) { int length = s.length(); //p[i][j]代表ij是否是回文串 boolean[][] p = new boolean[length][length]; int maxLen = 0;//记录最长长度 String maxPal = "";//记录最长回文串 for(int len = 1; len <= length; len++) { for(int start = 0; start < length; start++) { //len代表回文串长度,start起始位,end终止位 int end = start + len - 1; if(end >= length) break; //核心思想的代码,判断是否回文串 p[start][end] = (len == 1 || len == 2 || p[start + 1][end - 1]) && s.charAt(start) == s.charAt(end); /* 可以理解为 if((len == 1 || len == 2 || p[start + 1][end - 1]) && s.charAt(start) == s.charAt(end)) p[][] = true; */ if(p[start][end] && len > maxLen) { maxPal = s.substring(start, end+1); maxLen = len; } } } return maxPal; } }
来源:https://www.cnblogs.com/chenshaowei/p/12295339.html