最长回文子串

最长回文子串

1、参考资料

https://leetcode-cn.com/problems/longest-palindromic-substring/

https://blog.csdn.net/u013309870/article/details/70742315

https://zhuanlan.zhihu.com/p/38251499

https://labuladong.gitbook.io/algo/gao-pin-mian-shi-xi-lie/zui-chang-hui-wen-zi-chuan

2、题目要求

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例 1:

输入: "babad"
输出: "bab"
注意: "aba" 也是一个有效答案。

示例 2:

输入: "cbbd"
输出: "bb"

3、代码思路

方法一:中心扩散法

  1. 我们遍历字符串 str 中的每一个字符,以该字符为中心,向两边扩散求最长回文字符串

  2. 对于 "xabay" 这种字符串,存在中心对称点,左指针 left 和右指针 right 同时指向字符 'b' ,然后向两侧扩展

  3. 对于 "xabbay" 这种字符串,不存在中心对称点,左指针 left 指向左侧的字符 b ,右指针 right 指向右侧的字符 b,然后向两侧扩展

  4. 我们在遍历字符串 str 中的每一个字符,存在中心对称点和不存在中心对称点的情况都要考虑到,expandFromCenter() 方法以 leftright 为中心起点,向两侧扩展,寻找回文字符串

  5. 考虑到程序性能,我们在 expandFromCenter() 方法中,选择返回回文字符串的长度,并不是返回左右边界的索引 int[] {left, right},就是将链表长度再转换左右边界索引的时候,逻辑有点绕,举一些例子就明白了


方法二:动态规划法

4、代码实现

中心扩散法:时间复杂度 O(n2),空间复杂度 O(1)

/**
 * @ClassName LongestPalindromeDemo
 * @Description TODO
 * @Author Heygo
 * @Date 2020/9/3 14:22
 * @Version 1.0
 */
public class LongestPalindromeDemo {

    public static void main(String[] args) {
        Solution solution = new Solution();
        String longestPalindrome = solution.longestPalindrome("babad");
        System.out.println(longestPalindrome);
    }

}

class Solution {
    /**
     * 求 str 的最长回文字符串
     *
     * @param str 输入的字符串
     * @return str 的最长回文字符串
     */
    public String longestPalindrome(String str) {

        // Gurad safe
        if (str == null || str.length() < 1) {
            return "";
        }

        int start = 0;
        int end = 0;
        // 遍历字符串中每一个字符
        for (int i = 0; i < str.length(); i++) {
            // 以当前字符为中心对称点,以 i 为中心向两边扩散
            int len1 = expandFromCenter(str, i, i);
            // 无中心对称点,,以 i 为左指针,i+1 为右指针,向两边扩散
            int len2 = expandFromCenter(str, i, i + 1);
            // 求得最大的回文串长度
            int len = Math.max(len1, len2);
            // 如果当前回文串长度大于之前的回文串长度
            if (len > end - start) {
                // 对于 "xabay" 这种字符串,len = 3 为奇数
                // 对于 "xabbay" 这种字符串,len = 4 为偶数
                start = i - (len - 1) / 2;
                end = i + len / 2;
            }
        }
        // 返回最长回文字符串
        return str.substring(start, end + 1);

    }

    /**
     * 中心扩展法求 str 的最长回文字符串
     * 如果匹配像 "aba" 这样有中心对称点的字符串,left == right
     * 但如果匹配像 "abba" 这样没有中心对称点的字符串,right = left + 1
     *
     * @param str   源字符串
     * @param left  left 起点
     * @param right right 起点
     * @return 回文字符串的长度
     */
    public int expandFromCenter(String str, int left, int right) {

        while (left >= 0 && right < str.length() && str.charAt(left) == str.charAt(right)) {
            left--;
            right++;
        }

        // 回文字符串的长度
        // 对于 "xabay" 这种字符串,执行完成后 left 指向 x,right 指向 y,right - left - 1 = 3,为回文字符串的长度
        // 对于 "xabbay" 这种字符串,执行完成后 left 指向 x,right 指向 y,right - left - 1 = 4,为回文字符串的长度
        return right - left - 1;
    }
}
  • 3
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值