Leetcode 05最长回文子串(c++和python)

本文介绍了一种高效算法,用于在给定字符串中查找最长的回文子串。通过中心扩展法,算法能快速确定回文的起始位置和长度,适用于多种编程语言。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目描述:

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

示例 1:

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

示例 2:

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

解题思路:

简单直观的解法,回文是中心对称的,所以从第二个字符开始,判断是否是中心对称。

执行用时:12 ms, 在所有 C++ 提交中击败了95.47%的用户

内存消耗:7 MB, 在所有 C++ 提交中击败了89.26%的用户

C++代码:

class Solution {
public:
	string longestPalindrome(string s) {
        // 找到回文开始的索引start,和回文的长度max_len.

		int s_len = s.size();
        int start_idx = 0; // 最长回文开始的索引start
        int max_len = 0;  // 最长回文长度。
        // 1. 如果长度小于等于1,则字符串本身
        if (s_len <= 1) return s;
        // 2. 因为回文是对称的,从第二项开始,判断左右是否对称
        // 以i-1和i为中心的偶数长度回文,或者以i为z中中心的奇数长度回文
        for (int i = 1; i < s_len; i++)
        {
            // 3. 找是否有偶数长度的回文,向两边扩展,找到最左边索引low和最右边索引high
            int low = i-1, high=i;  // 初始时回文左右两边索引是i-1和i. abb
            while (0 <= low && high < s_len && s[low] == s[high])  // 左右不越界,并且字符相等
            {
                low--;
                high++;  // 符合以上两个条件,则更新回文的左右索引
            }
            // 找到后更新start_idx和max_len
            low++;  //上面多移动了一位
            high--;
            if (high - low + 1 > max_len) 
            {
                start_idx = low;
                max_len = high - low + 1;
            }

            // 找是否有奇数长度的回文,向两边扩展,找到最左边索引low和最右边索引high
            low = i-1, high = i+1;   // 回文中间索引是i,初始时两边索引是i-1和i+1. aba
            while (0 <= low && high <= s_len && s[low] == s[high])  
            {
                low--;
                high++;
            }
            // 找到后更新start_idx和max_len
            low++;
            high--;
            if (high - low + 1 > max_len) 
            {
                start_idx = low;
                max_len = high - low + 1;
            }
        }
        return s.substr(start_idx, max_len);
	}
};

简化版:

class Solution {
public:
    string longestPalindrome(string s) {
        // 回文是中心对称的
        if (s.size() <= 1) return s;
        int max_len = 0;
        int start_idx = 0;

        for (int i = 1; i < s.size(); i++)  // 以i-1和i为中心的偶数长度回文,或者以i为z中中心的奇数长度回文
        {
            // 查看是否有偶数长度的回文,有则会更新max_len和start_idx
            int low = i - 1, high = i; // 如果是偶数,中心对称,往两边扩展. abb
            huiwen_idx(s, low, high, max_len, start_idx);
            

            // 查看是否有奇数长度回文,有则会更新max_len和start_idx
            low = i-1; high = i+1;
            huiwen_idx(s, low, high, max_len, start_idx);
        }
        return s.substr(start_idx, max_len);
    }

    void huiwen_idx(string s, int low, int high, int &max_len, int &start_idx)
    {
        while (0 <= low && high < s.size() && s[low] == s[high])
        {
            low--;
            high++;
        }
        low++;
        high--;
        // 确认是否需要更新
        if (max_len < (high-low+1))
        {
            max_len = high - low + 1;
            start_idx = low;
        }
    }
};

 

对应的Python解法

python代码:

执行用时:444 ms, 在所有 Python 提交中击败了94.00%的用户

内存消耗:13.1 MB, 在所有 Python 提交中击败了79.54%的用户

class Solution(object):
    def longestPalindrome(self, s):
        """
        :type s: str
        :rtype: str
        """
        # 1, 长度为0或者1
        s_len = len(s)
        if s_len <= 1: 
            return s 
        # 获取最长回文开始的索引start_idx,和长度max_len
        
        start_idx = 0
        max_len = 0
        for i in range(1, s_len):
            # 2. 偶数回文中间位置是i-1, i
            low = i-1
            high = i
            while 0 <= low and high < s_len and s[low] == s[high]:
                low = low - 1
                high = high + 1
            low = low + 1  # 回到真实的回文左右索引
            high = high -1 
            # 判断长度是否比之前记录的长
            if high-low+1 > max_len:
                start_idx = low
                max_len = high - low + 1
            
            # 3.奇数回文中间位置是i
            low = i-1
            high = i+1
            while 0 <= low and high < s_len and s[low] == s[high]:
                low = low - 1
                high = high + 1
            low = low + 1
            high = high - 1
            if high-low+1 > max_len:
                start_idx = low
                max_len = high - low + 1
        
        return s[start_idx:start_idx+max_len]



        

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Mr.Q

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值