最长回文子串Java

求解最长回文子串的几种方法(Java版)

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

示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:
输入:s = "cbbd"
输出:"bb"

提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成

解法一、暴力解法

作为一个小菜鸡,这是我做题最容易想到的方法,就是找出每个字符串,判断是否是回文串,记录最长的子串返回即可。这种方法很容易想到,但是时间复杂度为O(n³),会超出时间限制。

//暴力解法
class Solution {
	public String longestPalindrome(String s) {
		//长度为1的字符串的单独考虑
     	if(s.length()==1)  return s;
    	int maxlength=0;
     	String ans="";
     	for(int i=0;i<s.length()-1;i++){
     		//注意j<=s.length(),因为substring(i,j) 截取的字符串区间是前闭后开的,即[i,j)
         	for(int j=i+1;j<=s.length();j++){		
             	String temp=s.substring(i,j);
            	if(isPalindrome(temp)&&temp.length()>maxlength){
                	ans=temp;
                	maxlength=ans.length();
            	}
         	}
    	}
     	return ans;
	}
	//判断是否是回文串的函数
	public boolean isPalindrome(String s){
    	int length=s.length();
    	for(int i=0;i<length/2;i++){
        	if(s.charAt(i)!=s.charAt(length-i-1))
            	return false;
    	}
    	return true;
	}
}

方法二、中心扩展法

回文串的最大的特点就是左右对称,所以,我们可以选定一个中心,每次循环往左右各扩展一位,只要左右这两个字符相等,那么它就是回文串。需要注意的是,偶数长度的回文串中心是最中间的两个字符,要把这两个字符作为中心扩展。

//中心扩散法
class Solution {
	public String longestPalindrome(String s) {
    	int length=s.length();
    	int start=0;
    	int end=0;
    	for(int i=0;i<length;i++){
        	int odd=getLength(s,i,i);
        	int even=getLength(s,i,i+1);
        	int temp=odd>even ? odd : even ;
        	//求出最长回文串的起始和终止位置,注意start与end的计算方法
        	if(temp>end-start){
            	start=i-(temp-1)/2;
            	end=i+temp/2;
        	}
    	}
    	return s.substring(start,end+1);
	}
	public int getLength(String s,int left,int right){
    	while(left>=0&&right<s.length()&&s.charAt(left)==s.charAt(right)){
        	left--;
        	right++;
    	}
    	//注意回文串长度的计算right-left+1-2
    	return right-left-1;
	}
}

方法三、动态规划

动态规划就是一种利用空间换时间的办法,设置一个二维布尔数组temp[][],假设temp[i][j]表示s[i]~s[j]为回文串,那么,temp[i][j]=true等价于temp[i+1][j-1]=true&&s[i]=s[j],例如"bab"为回文串,那么"#bab#"肯定也是回文串。对于temp的初始化就是一个字符肯定是回文串、两个相等的字符也是回文串。

class Solution {
	public String longestPalindrome(String s) {
    	int length=s.length();
    	if(length==1) {
        	return s;
    	} 
    	boolean[][] temp=new boolean[length][length];
    	int start=0;
    	int maxlength=1;
    	//temp初始化
   	 	for(int i=0;i<length;i++){
        	//一个字符肯定是回文
        	temp[i][i]=true;
        	//两个相等字符的也是回文
        	if(i<length-1&&s.charAt(i)==s.charAt(i+1)) {
            	temp[i][i+1]=true;
            	start=i;
            	maxlength=2;
        	}
    	}
    	//len表示回文串长度,len=3表示从长度为3的开始找起
    	for(int len=3;len<=length;len++){
        	//i表示字符串的起始位置,注意for循环条件防止越界
        	for(int i=0;len+i-1<length;i++){
            	//loc表示终止位置
            	int loc=i+len-1;
            	if(s.charAt(i)==s.charAt(loc)&&temp[i+1][loc-1]){
                	temp[i][loc]=true;
                }
            	if(temp[i][loc]&&len>maxlength){
                	start=i;
                	maxlength=len;
            	}
        	}
   	 	}
    	return s.substring(start,start+maxlength);
	}
}

版权声明:本文为m0_52254526原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。