最长回文字串的多种解法(java)

文章目录

    • 1.暴力解法
    • 2.中心扩散法
    • 3.动态规划法

题目要求:给你一个字符串 s,找到 s 中最长的
回文子串

1.暴力解法

列举所有子串;
将字符串分解为字符数组char[]arr,方便后续判断是否为回文字符串,接着使用两层for循环去跑字符串s,使用maxf初始化为1去记录最长回文字符串的长度,min记录最长字符串的起始下标。
代码如下:

public String longestPalindrome(String s) {
        int let=s.length();
        if(let<2){//s的字符长度小于2的直接返回自己
            return s;
        }
        char []arr=s.toCharArray();
        int min=0;//实时记录最长回文字符串的起始下标
        int maxf=1;//记录最长回文字符串的长度
        for(int i=0;i<let-1;i++){//只需到let-2下标
            for(int j=i+1;j<let;j++){
                if(ifzfc(arr,i,j)&&j-i+1>maxf){//是回文字符串且长度大于maxf满足条件
                    maxf=j-i+1;
                    min=i;
                }
            }
        }
        return s.substring(min,maxf+min);//右边下标左下标加上长度
    }
    public boolean ifzfc(char[] arr,int x,int y){//使用字符数组去判断是否为回文字符串
        while(x<y){
            if(arr[x]!=arr[y]){
                return false;
            }
            x++;
            y--;
        }
        return true;
    }

此方法时间复杂度为O(n^3)
两层for循环O(n^2)加上是否为回文字符串的判断O(n)
空间复杂度为O(1)

2.中心扩散法

遍历字符数组,以中心轴向两边扩散,注意奇偶性。
代码:

public String longestPalindrome(String s) {
        int ret=s.length();
        if(ret<2){
            return s;
        }
        char[]arr=s.toCharArray();
        int min=0;//实时记录最长回文字符串的左下标
        int maxf=1;
        for(int i=0;i<ret-1;i++){//这里i
            //分奇偶性
            int jiexpand=expand(arr,i,i);//奇
            int opand=expand(arr,i,i+1);//偶
            int maxjo=Math.max(jiexpand,opand);
            if(maxjo>maxf){
                maxf=maxjo;
                min=i-(maxjo-1)/2;//左下标的判断可以带几个特殊点判断
                }
            }
         return s.substring(min,min+maxf);
    }
    
    public int expand(char[]arr,int left,int right){
        while(left>=0&&right<arr.length){
            if(arr[left]==arr[right]){
                left--;
                right++;
            }
            else{
                break;
            }
        }
        //注意while结束时 去使用特殊点判断回文字符串长度与right,left之间的关系;当left==right时left--,right++,while跳出循环  长度:right-left+1-2=right-1;
        return right-left-1;
    }

此方法的时间复杂度为O(n^2);空间复杂度为O(1)

3.动态规划法

此方法的原理是利用当一个回文字符串去掉前后两字符时仍然是回文字符串
例如:abcba去掉了两边a字符串bcb仍然是回文字符串
要注意的是特殊性利用其特殊的地方和规律来篇写代码
代码:

  public String longestPalindrome(String s) {
      int ret=s.length();
      if(ret<2){
        return s;
      }
      int beign=0;
      int maxf=1;
      boolean [][]drap=new boolean[ret][ret];
   
      for(int i=0;i<ret;i++){
        drap[i][i]=true;
      }
         //boolean[i][j]表示s[i...j]是否为回文字符串
      for(int j=1;j<s.length();j++){//注意j从1开始
        for(int i=0;i<s.length();i++){
            if(s.charAt(i)!=s.charAt(j)){
                drap[i][j]=false;
            }
            else{
                if(j-i<3){ //因为当字符'i'=='j'时drap[i][j]=drap[i+1][j-1]所以(j-1)-(i+1)+1<2  => j-i<3
                    drap[i][j]=true;
                }
                else{
                    drap[i][j]=drap[i+1][j-1];
                }
            }
            if(j-i+1>maxf&&drap[i][j]){
                beign=i;
                maxf=j-i+1;
            }
        }
      }
      return s.substring(beign,beign+maxf);
    }

该时间复杂度为O(n^2);
空间复杂度为O(n^2);

你可能感兴趣的:(java)