leetcode刷题记录——5.最长回文串_C语言
- 前言:最近开始刷LeetCode,一开始有想过做笔记记录过程,但是一直拖着,刷到第五题优化代码后前后对比明显,赶紧记录一下。
-
题干
题目地址如下:https://leetcode-cn.com/problems/longest-palindromic-substring/
思路1:
起初想到的是从字串左端(头部s[0])一直遍历到右端(尾部s[length]),子字串长度由1开始慢慢增加,期间记录回文字串。到length后,字串左端往右走一格到s[1],重复遍历,直到字串左端减右端的长度小于已记录下的字串长度。
由于太过繁琐,所以就没有实现。
思路2:暴力解法
后面想到题目本身就是要求最长子字符串,那我先定一个length长度的区间,看看这个区间内是不是一整串回文数,是则输出,不是就①【区间长度减一,然后用这个区间由左到右的“套”原字符串】,当区间右端走到原字符串右端还未得到回文数的话,重复①操作,直至得到回文数则输出。
这个解法很直接暴力,如果遇到很长的字符串且都不是的话,则会疯狂遍历字串然后输出。。。一个字符,但是确实能用,代码如下:
#include "string.h"
char * longestPalindrome(char * s){
int lengthmax = strlen(s);
char *res = (char*)malloc(sizeof(char)*(lengthmax+1));
int rightnow_length = lengthmax,reduce_length = 0;
int left,right,excursion = 0,i;
if(lengthmax==1)
{
res[0] = s[0];
res[1] = '\0';
return res;
}
for(rightnow_length=lengthmax;rightnow_length>0;rightnow_length--)
{
excursion = 0;
reduce_length = lengthmax - rightnow_length;
do
{
left = 0+excursion;
right = rightnow_length+excursion-1;
while(left<right)
{
if(s[left] == s[right])
{
left++;
right--;
}
else
{
break;
}
}
if(left>=right)
{
for(i=0;i<rightnow_length;i++)
{
res[i] = s[i+excursion];
}
res[i] = '\0';
return res;
}
else
{
excursion++;
}
}while(excursion<=reduce_length);
}
return res;
}
运行后的效果:280ms 6MB
解出来后还是挺开心的,就是运行时间太久了,后面看到评论区有人的程序跑4ms,如下:
当时第一反应,我靠4ms?真的假的?赶紧Ctrl CV大神的代码跑了跑,嗯确实是4ms,不过内存达到了38.4MB。然后又仔细看了看大神的代码逻辑,也是遍历字符串,从第二个字符开始,找到与自己不相同的字符为中心字符,将遍历位置移到中心字符处,然后以中心字符向两边一一对比,不相同时计算长度,记录最长长度。按这个思路就可以大大减少遍历次数,好厉害啊,在看懂一些后,尝试在C语言上实现这个思路。最终代码如下:
#include "string.h"
char * longestPalindrome(char * s){
int lengthmax = strlen(s);
char *res = (char*)malloc(sizeof(char)*(lengthmax+1));
int left=0,right,i,j,len=0;
//排除单字符情况
res[0] = s[0];
res[1] = '\0';
if(lengthmax==1)
{
return res;
}
for(i=0;i<lengthmax;i++)
{
left = i;
right = left;
//找中心字符
while((right<lengthmax-1)&&(s[right+1]==s[left]))
{
right++;
}
//将遍历位置移到中心字符处
i = right;
//对比字符
while((left>0)&&(right<lengthmax-1)&&(s[right+1]==s[left-1]))
{
left--;
right++;
}
//记录最长字符长度及字符
if(right-left+1>len)
{
len = right-left+1;
for(j=0;j<len;j++)
{
res[j] = s[left+j];
}
res[j] = '\0';
}
}
return res;
}
最后运行出来:4ms 6MB
比起原来的暴力解法(280ms 6MB),内存不变,运行快了70倍!!!