LeetCode 5 最长回文子串(字符串、中心扩展)

16 篇文章 0 订阅

题目要求:

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

示例 1:

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

示例 2:

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

 

 

1.暴力解法

最容易想到的就是暴力解法,找出所有的子串,然后再一个个去判断是不是回文,然后再从中找到最长的那个。

求每一个子串时间复杂度O(N^2),判断子串是不是回文O(N),两者是相乘关系,所以时间复杂度为O(N^3)。

下面是代码:

C++代码1:

class Solution {
public:
    string longestPalindrome(string s) {
        string ret;
        
        for (int i = 0; i < s.size(); ++i) {
            for (int j = s.size() - 1; j > i; --j) {
                string temp = s.substr(i, j - i + 1);
                if (isPalindromic(temp)) {
                    if (temp.size() > ret.size()) {
                        ret = temp;
                        break;
                    }
                }
            }
        }
        
        if (ret.empty() && !s.empty()) {
            ret = s[0];
        }
        
        return ret;
    }
    
    bool isPalindromic(string s) {
        bool ret = true;
        
        for (int i = 0, j = s.size()-1; i < j; ++i, --j) {
            if (s[i] != s[j]) {
                ret = false;
                break;
            }
        }
        
        return ret;
    }
};

 

 

 

结果:

该方法最后时间超出,未能AC

 

 

 

解析:

“回文串”就是一个正读和反读都一样的字符串,比如“level”或者“noon”等。

暴力解法就是用2个for循环,遍历该字符串的每一种可能性的子串,然后判断该子串是不是回文串,最后给出最长回文子串。
因为longestPalindrome函数里通过2个for循环去找每一种可能性的子串,然后该函数内部又调用了isPalindromic函数,里面又有一个for循环去判断该子串是否是回文串,所以该方法总的时间复杂度为O(n^3)。

所以需要继续优化。

 

 

 

 

2.中心扩展

中心扩展就是把给定的字符串的每一个字母当做中心,向两边扩展,这样来找最长的子回文串。算法复杂度为O(N^2)。

但是要考虑两种情况:

1、像aba,这样长度为奇数。

2、想abba,这样长度为偶数。

C++代码2:

class Solution {
public:
    string longestPalindrome(string s) {
        if (s.size() <= 1) {
            return s;
        }
        
        string ret;
        int start = 0, end = 0;
        for (int i = 1; i < s.size(); ++i) {
            // 偶数回文遍历的方式,abba这类回文从中心向两边遍历
            start = i - 1;
            end = i;
            
            while (start >= 0 && end < s.size() && s[start] == s[end]) {
                --start;
                ++end;
            }
            
            int paliStart = start + 1, paliEnd = end - 1;
            int paliLen = paliEnd - paliStart + 1;
            if (paliLen > ret.size()) {
                ret = s.substr(paliStart, paliLen);
            }
            
            // 奇数回文遍历方式 abcba这种方式,中心点start=i-1, end = i+1
            start = i - 1;
            end = i + 1;
            while (start >= 0 && end < s.size() && s[start] == s[end]) {
                --start;
                ++end;
            }
            
            paliStart = start + 1;
            paliEnd = end - 1;
            paliLen = paliEnd - paliStart + 1;
            if (paliLen > ret.size()) {
                ret = s.substr(paliStart, paliLen);
            }
        }
        
        return ret;
    }
};

 

 

 

 

结果:

 

 

 

 

解析:

从其中一个字符开始,左右向外扩展得到一个更长的子串,看是否是回文子串,如果是回文子串,
则继续向外遍历,直到遇到非回文子串或者超出子串范围。此方法的时间复杂度O(N^2);但是需要
注意针对一个字符向外扩张时,需要同时考虑偶数字符个数回文子串和奇数字符个数回文子串两种情况。

代码还是比较好懂的。

 

 

 

 

 

这里主要介绍了暴力解法和中心扩展2种方法

更多详细的解法,请看以下链接:

https://blog.csdn.net/kangroger/article/details/37742639

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值