leetcode-Longest Palindromic Substring

来源:互联网 发布:日本航空发动机 知乎 编辑:程序博客网 时间:2024/06/05 06:51

首先解释题目的意思:

 Palindromic Substring是“回文”的意思。

什么是回文呢?它是一种修辞手法。如“凤落梧桐梧落凤”这句话就是用了回文的修辞。

这道题目的意思是让你求一个字符串中的最长回文串,如“ababc”中最长回文串是“aba”.

暴力方法:时间复杂度O(n^2),空间复杂度O(1)(读了leetcode上的一篇文章后发现,还有更暴力的方法,时间复杂度是O(n^3),该方法直接判断源字符串的每个子字符串是不是回文。。本菜突然觉得进步了一点点。)

思路:分别以每个字符为中心,遍历以其为中心的字符串是不是回文,并取最长回文。下面举一个例子

str = abab

以str[0](即第一个a)为中心,最长扩展半径是0(因为它已经是左边界了,以它为中心的字符串长度最大只能是1),最长回文只能是a;

以str[1](即第一个b)为中心,最长扩展半径是1(因为它的左右两边都有字符,但是以它为中心,最多只能扩展1位,因为如果扩展2位,左边就越界了,所以以它为中心的子字符串的最大长度是3),最长回文是aba;

以str[2](即第二个a)为中心,最长扩展半径是1(以它为中心,最多只能扩展1位,因为如果扩展2位,右边就越界了,所以以它为中心的子字符串的最大长度是3),最长回文是bab;

以str[3](即第二个b)为中心,最长扩展半径是0(因为它已经是右边界了,以它为中心的字符串长度最大只能是1),最长回文只能是b;

检测最长回文的思想:首先需要分类,一类是最长回文字符串长度为奇数,另一类是长度为偶数(上面分析的只是最长回文字符串长度为奇数的情况),具体如何检测,情况代码。

代码如下:

char* longestPalindrome(char* s) {
//最直观的方法——用每个点做回文终点,遍历所有可能性,时间复杂度为n^2
//稍微改进的方法——从中间点开始找,记录当前找到的最大回文串长度,
//如s长为5,中点最大回文长3,其它点就不用找了
int index_max, index_current;
int srcLen = 0;
bool oddlen = true;
int maxlen = 0;
while (s[srcLen] != '\0')
{
srcLen++;
}
int srcLen_d1 = srcLen - 1;


int radius_posibal_odd, radius_posibal_even;
int i = 0;
for (index_current = 0; index_current < srcLen; index_current++)
{
int len, substrcount;
radius_posibal_odd = index_current>(srcLen - index_current - 1) ? srcLen - index_current - 1 : index_current;
radius_posibal_even = index_current + 1 > srcLen - 1 - index_current ? srcLen - 1 - index_current : index_current + 1;
if (maxlen < 1 + radius_posibal_odd * 2)
{
//回文串长度为奇数
i = 1;
len = 0;
substrcount = 0;
while (i <= radius_posibal_odd)
{
if (s[index_current - i] == s[index_current + i])
substrcount++;
else
{
len = substrcount * 2 + 1;
if (len > maxlen)
{
maxlen = len;
oddlen = true;
index_max = index_current;
}
break;
}
i++;
}
len = substrcount * 2 + 1;
if (len > maxlen)
{
maxlen = len;
oddlen = true;
index_max = index_current;
}
}
if (maxlen < radius_posibal_even * 2)
{
//回文串长度为偶数
i = 0;
len = 0;
substrcount = 0;


while (i<radius_posibal_even)
{
if (s[index_current - i] == s[index_current + 1 + i])
substrcount++;
else
{


len = substrcount * 2;
if (len>maxlen)
{
maxlen = len;
oddlen = false;
index_max = index_current;
}
break;
}
i++;
}
len = substrcount * 2;
if (len > maxlen)
{
maxlen = len;
oddlen = true;
index_max = index_current;
}
}
}
int index_rs;
if (oddlen)
{
index_rs = index_max - (maxlen - 1) / 2;
}
else
{
index_rs = index_max - (maxlen / 2 - 1);
}
char *rs = (char*)malloc((maxlen + 1)*sizeof(char));
for (i = 0; i < maxlen; i++)
{
rs[i] = s[index_rs + i];
}
rs[i] = '\0';
return rs;
}


动态规划法:时间复杂度O(n^2),空间复杂度O(n^2),空间复杂度可以优化到O(n)

连接如下:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-i.html


C 0ms解法(其实该方法就是最开始的“暴力方法”的优化,但是给出该方法的人说该方法的时间复杂度是O(n)):

char* longestPalindrome(char* s) {
char *go,*max_start,*left,*right,*re;
int max_length,temp_length;
char *s_end;
s_end = s+strlen(s);
if (strlen(s) == 0) return s;
if (strlen(s) == 1) return s;
for(go = s,max_length = 1;go<s_end;)
{
    if (s_end - go <= max_length * sizeof(char) / 2) break;
    left = go,right = go;
    while(*right==*(right+1)) right++;
    go = right + 1;
    while(left<s_end && left>s && *(left-1) == *(right+1))
    {
        right++;
        left--;
    }
    temp_length = (right-left)/sizeof(char) + 1;
    if(temp_length > max_length) {
        max_start = left;
        max_length = temp_length;
    }
}
re =(char *) malloc(max_length*sizeof(char)+1);
go = re;
while(max_length)
{
    *(go) = *(max_start);
    go++;
    max_start++;
    max_length--;
}
*go = '\0';
return re;

manacher's 算法:

没搞明白,而且算法速度也没有上面的方法块。。。记录它的原因是因为它需要重新构造一个字符串,目的是为了省去回文串长度为偶数和奇数时算法上的不同。

字符添加方法举例如下:添加前的字符串为abc,添加之后变为#a#b#c#。

具体原理讲解在:

英文原文:http://articles.leetcode.com/2011/11/longest-palindromic-substring-part-ii.html

汉语译文:http://www.cnblogs.com/bitzhuwei/p/Longest-Palindromic-Substring-Part-II.html

0 0
原创粉丝点击