leetcode刷题记录——5.最长回文串_C语言

leetcode刷题记录——5.最长回文串_C语言

  • 前言:最近开始刷LeetCode,一开始有想过做笔记记录过程,但是一直拖着,刷到第五题优化代码后前后对比明显,赶紧记录一下。
  1. 题干
    题目地址如下:

    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倍!!!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值