计算机低能儿从0刷leetcode | 5. 最长回文子串(踩了好多坑)

题目:5. 最长回文子串

解答:

class Solution {
public:
    string longestPalindrome(string s) {
       int n=1,maxlen=1;//定义回文串长度n,回文串最大长度maxlen
       int res_left=0;//定义为找到的结果字符串的左端点
       if(s.length()==1||s.length()==0) return s;

       for(int i=0;i<s.length();i++){
        int l=i-1,r=i+1;
        n=1;

        while(r<s.length()&&s[r]==s[i]){//向右扩散    
                r++;
                n++;
        }

        while(l>=0&&r<s.length()&&s[l]==s[r]){//向左和向右同时扩散         
                l--;r++;
                n+=2;
        }

        if(n>maxlen){//更新maxlen和起点res_left
            maxlen=n;
            res_left=++l;
         }
       }

       string res;
      
       for(int i=res_left;i<=res_left+maxlen-1;i++)
           res.push_back(s[i]);//把找到的最长回文串放进结果数组中
       return res;
    }
};

方法:本题采用中心扩散法(看题解说是叫这个名儿)

1、采用一个大的for循环对字符串s从左到右遍历一次。

2、其中包含两个while循环,第一个处理当前遍历到的元素s[i]与s[r]相等的情况,实现”向右扩散“,第二个处理元素两侧s[l]与s[r]相等的情况,实现“向左向右同时扩散”。

误区:

此方法看起来简单易懂,但其实有很多重要的细节,比如让我们思考以下几个问题:

1、为什么这段代码中没有向左扩散的while循环呢?

2、向左向右扩散时,s[l]和s[r]一定是关于s[i]对称的吗?

3、这两个循环的顺序是否有严格要求?

问题一:我们从左至右遍历字符串s,并在每个位置都尝试向右扩散,比如当s为“a b b b”时,我们遍历到i=1时,便可以向右扩散从而找到“b b b”这个回文串,因此当i=2、3时,向左遍历是多余的。可见我们不需要向左遍历,也可以考虑到所有情况。

问题二:这是不一定的,很有可能首先向右扩散了。比如“a b b b b a c”,当i=1时,初始l=0、r=1,经过向右扩散后l=0、r=5,然后再向左向右扩散,比较的是s[0]与s[5],而这两个元素并不关于s[1]对称。

问题三:必须先向右扩散、再向左向右扩散。比如“b a b a c”,如果我们将两个while循环换了位置,当i=1时,首先向左向右扩散,跳出第一个while循环时l=-1、r=3,此时我们进入第二个while循环,比较s[i]与s[r],会发现相等,从而向右扩散,认为“b a b a”是一个回文串,很明显错误。因此两个循环的顺序不可以随意调换。

如果对您有帮助并且您方便的话,期待您可以打赏一下,感谢!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

我哋每一个人都要ga油啊

您的鼓励是支持我继续的极大动力

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

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

打赏作者

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

抵扣说明:

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

余额充值