最长回文子串
最长回文子串
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
(1)暴力破解
class Solution {
public String longestPalindrome(String s) {
//使用暴力破解的方式进行求解
//首先判断字符串的长度是否是在可以产生回文子串
//如果该字符串的长度小于2 为 1 或 0 的话则最长回文子串就是本身
int len = s.length();
if(len < 2){
return s;
}
//定义right定义的最大长度
//left控制最小的
int right = 1;
int left = 0;
char[] ArrayList = s.toCharArray(); //java 中类将字符串转换为字符串数组
//枚举所有长度大于一的字符串
for(int i = 0; i < len - 1; i++){
for(int j = i + 1; j < len; j++) {
if(j - i + 1 > right && huiwen(ArrayList, i, j)) {
right = j - i + 1;
left = i;
}
}
}
return s.substring(left, left + right); //java 常用的类,将字符串转化为子字符串
}
//定义一个布尔函数判断数组是否为回文字符串
//定义一个数组, 左指针右指针
private boolean huiwen(char[] array, int left, int right){
//如果满足left < right则证明数组中含有元素
while(left < right){
//判断左下标对应的值 和右下标对应的值相等 则满足回文子串
//如果想等满足的话left向右移动 right向左移动
//依次遍历完left - right中的所有数组元素 如果均相等的话则返回true
if(array[left] != array[right]){
return false;
}
left++;
right--;
}
return true;
}
}
(2)中心扩展算法
**利用和动态规划相似的想法,可以得出这个中心扩展的算法 **
需要注意的是,在这个过程中需要考虑好它的几种特殊情况 以及对于下标的把控,控制其不会下标越界
class Solution {
public String longestPalindrome(String s) {
//使用中心扩展的方法进行求解
//先对特殊情况进行判断
//如果字符串为空或者是字符串的长度小于1 直接返回一个空的字符串
if(s == null || s.length() < 1) {
return " ";
}
//定义两个控制变量, 一个控制开始,一个控制结束
int left = 0, right = 0;
//开始遍历数组中的元素
for(int i = 0; i < s.length(); i++) {
//这里要讨论两种情况 分别是字符串为奇数和偶数是的情况
//奇数时最中间是一个字符 i
int len1 = center(s, i, i);
//偶数时最中间是两个字符 i 和 i-1
int len2 = center(s, i, i + 1);
//分别将得到的两个最长回文子串比较取出最大的值
int len = Math.max(len1, len2);
if(len > right - left) {
//然后判断分别得出最长回文子串的最小下标和最大的下标
//这个公式对于奇数个和偶数个都是用
left = i - (len - 1) / 2;
right = i + len / 2;
}
}
return s.substring(left, right + 1);
}
//创建一个方法用来体现中心扩展算法,判断从i开始的字符串向两边延伸从而得到最长回文字符串
public int center(String s, int left, int right){
//当满足left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right条件时 可以判断为是回文子串
while(left >= 0 && right < s.length() && s.charAt(left) == s.charAt(right)) {
--left;
++right;
}
//返回回文字符串下标之间的距离
return right -left - 1;
}
}
(3) Manacher 算法
之后补充 点击爱寂寞的时光博客
(4)动态规划
使用动态规划算法,在暴力破解的基础上降低了时间复杂度
动态规划就是通过牺牲空间的做法来实现时间上的更优
class Solution {
public String longestPalindrome(String s) {
//使用动态规划方式进行求解
int len = s.length();
if(len < 2){
return s;
}
//定义两个边界值
int maxLen = 1;
int begin = 0;
//开始使用动态规划算法
//dp[i][j]表示s[i ,j]是否是回文串
boolean[][] dp = new boolean[len][len];
char[] Array = s.toCharArray();
//二维数组中的对角线取不到值, 所以进行初始化
//二维数组中横坐标表示数组的右边界值,纵坐标是左边界值
for(int i = 0; i < len; i++) {
dp[i][i] = true;
}
for(int j = 1; j < len; j++) {
for(int i = 0; i < j; i++) {
if(Array[i] != Array[j]) {
dp[i][j] = false;
}else{
if(j - i < 3) {
dp[i][j] = true;
}else{
dp[i][j] = dp[i + 1][j - 1];
}
}
//只要dp[i][j] == true 成立,则表示s[i...j]为回文串
if(dp[i][j] && j - i + 1 > maxLen) {
maxLen = j -i + 1;
begin = i;
}
}
}
return s.substring(begin, begin + maxLen);
}
}
参考LeetCode