算法小知识----11.24----最长回文子串

212 阅读2分钟

这是我参与11月更文挑战的第24天,活动详情查看:2021最后一次更文挑战

最长回文子串

该题出自力扣的第五题——最长回文子串(中等题),题目是消化于官方题解

审题

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

输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。
  • 题目相当简单,就是找出字符串的最长回文子串

    • 什么是回文子串呢?

      • 借鉴于评论区——回文的意思是正着念和倒着念一样,如:上海自来水来自海上
    • 解题思路

      • 回文子串也就是说需要中心点,并向两边扩张,所以找到中心点便成了解题关键
  • 原本的想法很单纯也很接近——双指针

    • 那么问题出在哪里呢,出在移动指针的处理方式上,也就是中心点的定位上
    • 无论是移动一边还是双向移动,都无法满足题解
    • 因为题解需要任意一个点都有可能成为中心点
        public static String longestPalindrome(String s) {
            int n = s.length();
            boolean flag = false;
            if ((n & 1) == 0)flag = true;
            int resultLeft = -1;
            int resultRight = -1;
            int left = 0,right = n - 1;
            while (left<right){
                if (s.charAt(left) != s.charAt(right)){
                    resultLeft = -1;
                    resultRight = -1;
                }else {
                    if (resultLeft == -1 && resultRight == -1){
                        resultLeft = left;
                        resultRight = right;
                    }
                }
                left++;
                right--;
            }
            if (resultLeft !=-1 && resultRight != -1){
                return s.substring(resultLeft,resultRight+1);
            }
            return String.valueOf(s.charAt(0));
    ​
        }
    

编码

我们枚举所有的回文中心也就是选择中心点,并尝试扩展,直到无法扩展为止,此时的回文串长度即为此回文中心下的最长回文串长度。我们对所有的长度求出最大值,即可得到最终的答案。

  • 对于长度小于2的字符串直接返回
  • 循环整个长度,对当前下标作为中心点计算长度,包括奇偶数
  • 比较最长长度,并对起始末尾进行赋值
    public static String longestPalindrome(String s) {
        int n = s.length();
        if (n<2)return s;
        int left = 0,right = 0;
        for (int i = 0;i<n;i++){
            int odd = longers(s,i,i);
            int event = longers(s,i,i+1);
            int max = Math.max(odd,event);
            if (max > right - left){
                left = i-(max - 1)/2;
                right = i+max/2;
            }
        }
        return s.substring(left,right+1);
    }
​
    public static int longers(String s,int left,int right){
        while (left>=0 && right<s.length() && s.charAt(left) == s.charAt(right)){
            left--;
            right++;
        }
        return right - left -1;
    }

QQ截图20211124233227.png