Leetcode5 最长回文子串 C++,Java,Python

LeetCode5 最长回文子串

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/longest-palindromic-substring/

博主Githubhttps://github.com/GDUT-Rp/LeetCode

最长回文子串

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

示例 1:

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

示例 2:

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

思路

中心扩展算法

对字符串的每一个字符进行中心展开,找到最长的回文子串

Python
# -*- coding: utf-8 -*-

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


def create_sample():
    return "babad"


class Solution:
    def longestPalindrome(self, s):
        """
        中心扩展算法,时间复杂度 O(n^2),由于围绕中心来扩展回文会耗去 O(n)的时间
        :type s: str
        :rtype: str
        """
        length = len(s)
        if length < 1:
            return ""
        start, end = 0, 0   # 记录最长回文串左索引和右索引
        for i in range(length):
            len1 = self.expandAroundCenter(s, i, i)
            len2 = self.expandAroundCenter(s, i, i + 1)
            len3 = max(len1, len2)
            if len3 > end - start:
                start = i - (len3 - 1) // 2     # 跟新最长回文串的左索引
                end = i + len3 // 2             # 跟新最长回文串的右索引
        return s[start: end + 1]

    def expandAroundCenter(self, s, left, right):
        """
        中心扩展算法辅助函数,返回长度
        :rtype: int 长度
        """
        while left >= 0 and right < len(s) and s[left] == s[right]:
            left -= 1
            right += 1
        return right - left - 1

if __name__ == '__main__':
    solution = Solution()
    ans = solution.longestPalindrome(create_sample())
    print(ans)
Java
public String longestPalindrome(String s) {
    if (s == null || s.length() < 1) return "";
    int start = 0, end = 0;
    for (int i = 0; i < s.length(); i++) {
        int len1 = expandAroundCenter(s, i, i);
        int len2 = expandAroundCenter(s, i, i + 1);
        int len = Math.max(len1, len2);
        if (len > end - start) {
            start = i - (len - 1) / 2;
            end = i + len / 2;
        }
    }
    return s.substring(start, end + 1);
}

private int expandAroundCenter(String s, int left, int right) {
    int L = left, R = right;
    while (L >= 0 && R < s.length() && s.charAt(L) == s.charAt(R)) {
        L--;
        R++;
    }
    return R - L - 1;
}

复杂度分析

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2), 由于围绕中心来扩展回文会耗去 O ( n ) O(n) O(n) 的时间,所以总的复杂度为 O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( 1 ) O(1) O(1)

Manacher算法 马拉车算法

Manacher 算法的时间复杂度为 O(n)

https://subetter.com/articles/manacher-algorithm.html

Python
# -*- coding: utf-8 -*-

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


def create_sample():
    return "babad"


class Solution:
    def manacher(self, s):
        """
        Manacher算法,时间复杂度O(n)
        :param s:
        :return:
        """
        t = '%#' + '#'.join(list(s)) + '#$'
        length, sup, res = len(t), 0, 0
        li = [1] * length
        reach = pos = 0
        t += '%'
        for i in range(2, length - 1):
            if reach > i:
                if li[2 * pos - i] < reach - i:
                    li[i] = li[2 * pos - i]
                else:
                    li[i] = reach - i + 1
            while t[i + li[i]] == t[i - li[i]]:
                li[i] += 1
            if i + li[i] - 1 > reach:
                reach = i + li[i] - 1
                pos = i
            if li[i] > sup:
                sup = li[i]
                res = i
        return t[res - sup + 2: res + sup:2]

    def fastest(self, s):
        length = len(s)
        if length < 2 or s == s[::-1]:  # 长度为1或者翻转也全等
            return s
        max_len, begin = 1, 0
        for i in range(1, length):
            odd = s[i - max_len - 1:i + 1]
            even = s[i - max_len:i + 1]
            if i - max_len >= 1 and odd == odd[::-1]:
                begin = i - max_len - 1
                max_len += 2
                continue
            if i - max_len >= 0 and even == even[::-1]:
                begin = i - max_len
                max_len += 1
        return s[begin:begin + max_len]


if __name__ == '__main__':
    solution = Solution()
    ans = solution.manacher(create_sample())
    print(ans)

Java
package com.leetcode.rp;

class SolutionOfLeetCode7 {
    public int reverse(int x) {
        int flag = 1;
        String string;
        if (x < 0){
            flag = -1;
            string = x + "";
            string = string.substring(1, string.length());
        }
        else{
            string = x + "";
        }
        String newstring = new String();
        int length = string.length();
        for (int i = length - 1; i > -1; i--) {
            newstring += string.charAt(i);
        }
        try {
            x = Integer.parseInt(newstring);
        } catch (NumberFormatException e) {
            return 0;
        }
        return x * flag;
    }
    public int easy(int x){
        int ans = 0;
        int yu = 0;
        while (x != 0){
            yu = x % 10;
            x = x / 10;
            if (ans > Integer.MAX_VALUE / 10 || ans < Integer.MIN_VALUE / 10)
                return 0;
            ans = ans * 10 + yu;
        }
        return ans;
    }
}
public class LeetCode7 {
    public static void main(String[] args) {
        SolutionOfLeetCode7 solutionOfLeetCode7 = new SolutionOfLeetCode7();
        int[] x = {123, -123, 120, 21, 1534236469, -2147483648};
        for (int i:x) {
            int ans = solutionOfLeetCode7.reverse(i);
            System.out.println(ans);
            System.out.println(solutionOfLeetCode7.easy(i));
        }
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值