取消

5.最长回文子串

LeetCode题库-5.最长回文子串解题方法


回文串解释

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

简单解法

  1. 通过上面的解释很容易写出一个判断回文串的逻辑,判断第一位和最后一位是否相同,第二位和倒数第二位是否相同,直到字符串的中部:
1
2
3
4
5
6
7
8
9
10
11
public bool IsHuiWen(string s)
{
    for (int i = 0; i < s.Length / 2; i++)
    {
        if (s[i] != s[s.Length - 1 - i])
        {
            return false;
        }
    }
    return true;
}

2.对传入的字符串取所有子字符串,依次调用判断逻辑,找到最长的子字符串就行了,为了加快查找速度,我们从最长的子字符串开始,如果要判断的比现在找到的还短那就不用判断了,因为就算是回文串也不是最长的

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
public string LongestPalindrome(string s)
{
    var maxLength = 0;
    var maxString = "";
    for (int i = 0; i < s.Length; i++)
    {
        if (maxLength > s.Length - i)
        {
            break;
        }
        for (int j = s.Length; j > i; j--)
        {
            if (maxLength > j - i)
            {
                break;
            }
            if (IsHuiWen(s.Substring(i, j - i)) && j - i > maxLength)
            {
                maxLength = j - i;
                maxString = s.Substring(i, j - i);
            }
        }
    }
    return maxString;
}

无奈重写的算法

上面的解法简单好理解,但是通过不了,因为下面这个字符串判断时超过了leetcode认为的最大时间。 我觉得leetcode的服务器太水了,于是我去看了下推荐答案的时间:3ms。我的算法执行也才800+ms,差值不到1s还是很小的啊。但是没办法还是要改啊。

1
"aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabcaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"

第一种是通过遍历子字符串,如果字符串很长(最大1000)遍历的次数还是比较多的,用排列组合可以简单算一下(我不会,反正挺多的),所以还是用最开始想到的方法(因为开始我觉得太麻烦了就没实现)。 从回文串的解释中可以推出,回文串从中间开始向两边推也是相同的,回文串长度可能是奇数或偶数,这两种情况稍有差别,如:bab和baab,中值位置不一样。需要分别考虑(合并考虑我不会)。 这样就可以减少子字符串的截取操作,少一次循环。这样大概在3-4ms左右,比我第一个算法性能提高200倍,还是很牛逼的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
public string LongestPalindrome(string s)
{
    var maxLength = 0;
    var maxStr = "";
    for (int i = 0; i < s.Length; i++)
    {
        var curMaxLength = 1;
        while (i - curMaxLength >= 0 && i + curMaxLength < s.Length)
        {
            if (s[i - curMaxLength] != s[i + curMaxLength])
            {
                break;
            }
            curMaxLength++;
        }
        curMaxLength--;//curMaxLength最后一次是不符合的,所以要去掉最后一次自增
        if (maxLength < (curMaxLength * 2 + 1))
        {
            maxLength = (curMaxLength * 2 + 1);
            maxStr = s.Substring(i - curMaxLength , curMaxLength * 2 + 1);
        }
        curMaxLength = 0;
        while (i - curMaxLength >= 0 && i + curMaxLength + 1 < s.Length)
        {
            if (s[i - curMaxLength] != s[i + curMaxLength + 1])
            {
                break;
            }
            curMaxLength++;
        }
        curMaxLength--;
        if (maxLength < (curMaxLength + 1) * 2)
        {
            maxLength = (curMaxLength + 1) * 2;
            maxStr = s.Substring(i - curMaxLength, (curMaxLength + 1) * 2);
        }
    }
    return maxStr;
}

参考资料

本文会经常更新,请阅读原文: https://dashenxian.github.io/post/5.%E6%9C%80%E9%95%BF%E5%9B%9E%E6%96%87%E5%AD%90%E4%B8%B2 ,以避免陈旧错误知识的误导,同时有更好的阅读体验。

知识共享许可协议

本作品采用 知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议 进行许可。欢迎转载、使用、重新发布,但务必保留文章署名 小神仙 (包含链接: https://dashenxian.github.io ),不得用于商业目的,基于本文修改后的作品务必以相同的许可发布。如有任何疑问,请 与我联系 (125880321@qq.com)

登录 GitHub 账号进行评论