Leetcode 05:最长回文子串

题目描述:

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

注:回文串就是正着读和反着读是一样的,例如:上海自来水来自海上。包括我们之前学习C语言的时候,也有回文数,如:12344321。

示例 1:

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

示例 2:

输入:s = "cbbd"
输出:"bb"

示例 3:

输入:s = "a"
输出:"a"

示例 4:

输入:s = "ac"
输出:"a"

解法一:暴力破解法。

思路:暴力破解法很好理解,通过两层for循环来判断回文数,外层for循环遍历字符串,内层for循环从外层for循环的下一个位置开始逐一判断。最终得到最长的回文子串。暴力破解法的时间复杂度为O(n^2)。

代码:

public class Solution {

    public String longestPalindrome(String s) {
        //如果字符串长度小于2,直接返回
        if ( s.length() < 2) {
            return s;
        }
        //最长回文子串的长度
        int max = 0;
        int begin = 0;
        // s.charAt(i) 每次都会检查数组下标越界,因此先转换成字符数组
        char[] charArray = s.toCharArray();
        // 枚举所有长度大于 1 的子串 charArray[i..j]
        for (int i = 0; i <  s.length() - 1; i++) {
            for (int j = i + 1; j <  s.length(); j++) {
                if (j - i + 1 > max && isPalinedrome(charArray, i, j)) {
                    max = j - i + 1;
                    begin = i;
                }
            }
        }
        return s.substring(begin, begin + max);
    }

    /**
     * 判断子串是否为回文串
     */
    public  boolean isPalinedrome(char[] charArray, int left, int right) {
        while (left < right) {
            if (charArray[left] != charArray[right]) {
                return false;
            }
            left++;
            right--;
        }
        return true;
    }
}

解法二:中心扩散法。

思路:在遍历字符串的时候,对于每一个字符,以当前字符为中心向两边扩散,从而查找得到最长的回文子串。这里有一个很重要的问题在于:回文串的长度为奇数和偶数的时候,其中兴位置时不同的,所以其判断方式也会有所变化。以示例1和示例2为例,如下图:

因此,针对于上述的奇数和偶数两种情况,采用不同的方式去处理,如下:

(1)如果为奇数,则由i位置向两边开始扩散。

(2)如果为偶数,则由i和i+1分别向左右开始扩散。

代码:

public class Solution {

    public String longestPalindrome(String s) {
         //如果字符串长度小于2,直接返回
      if(s.length() < 2){
          return s;
      }
      //回文子串的长度
      int max = 0;
      //数组:res[0]代表起始位置,res[1]代表终止位置
      int[] res = new int[2];
      //字符串长度为奇数时,从i开始向两边扩散。对比对应位置的值。
       //字符串长度为偶数时,从i开始向左扩散,从i+1开始向右扩散。
      for(int i=0; i < s.length()-1; i++){
          int[] odd = getPosAndLen(s, i, i);
          int[] even = getPosAndLen(s, i, i+1);
          //判断回文子串的长度。
          int[] maxArr = odd[1] > even[1] ? odd : even;
          //如果长度大于max,则更新max和res
          if(maxArr[1] > max){
              max = maxArr[1];
              res = maxArr;
          }
      }
      return s.substring(res[0], res[0] + res[1]);
    }
    public int[] getPosAndLen(String s, int left, int right){
        //从left和right开始比较对应位置的值是否相同
        while(left >= 0 && right < s.length()){
            if(s.charAt(left) == s.charAt(right)){
                right++;
                left--;
            }else{
                break;
            }
        }
        return new int[]{left +1, right-left-1};
    }

}

猜你喜欢

转载自blog.csdn.net/weixin_47382783/article/details/118853305
今日推荐