C语言力扣刷题1——最长回文字串[双指针]

一、博客声明

  找工作逃不过刷题,为了更好的督促自己学习以及理解力扣大佬们的解题思路,开辟这个系列来记录。代码可能不是自己写的,更多的是理解大佬们的解题思路。


二、题目描述

给你一个字符串 s,找到 s 中最长的回文子串。
 
示例 1:
输入:s = "babad"
输出:"bab"
解释:"aba" 同样是符合题意的答案。

示例 2:
输入:s = "cbbd"
输出:"bb"
 
提示:
1 <= s.length <= 1000
s 仅由数字和英文字母组成

三、解题思路

1、思路说明

  这题主要使用双指针的方法来解决,以回文字的中间位置为突破口,让这两个指针在循环的时候朝着相对的方向移动,给定相应的判断条件来解决问题需求。在过程中求得最大回文字的长度以及第一个字在数组中的位置,最后用strncpy函数来返回目标回文字。

  第一种情况: 如果数组的长度小于等于1,则直接返回原来的数组就可以了

  第二种情况: 如果数组的长度大于1,则如下图,先用for循环遍历整个数组,在遍历数组中每个元素的时候用left和right对向移动,并同时用while循环判断s[left]s[right]是否相等,若相等left--right--。从对上申请两个int大小的内存,用于每次while结束后存储回文字的长度right - left - 1,以及第一个字在数组中的位置left + 1。在这种情况下,我们还需要考虑回文字长度是奇数还是偶数,如果是奇数的话,我们可以设置初始值left=right=i;若为偶数,则可以left=i,right=i+1。用len1记录奇数情况len2记录偶数情况。求最大的len作为最终结果。
在这里插入图片描述

2、知识补充

a、malloc动态内存分配

  malloc命令是从“堆”上面申请内存,内存是匿名的,类型和大小需要自己指定,返回的是指针(首指针,相当于数组第一个元素对应的地址)。申请地址的写法如下:

//从堆申请了2个int大小的内存,并把首地址给ret
int* ret = malloc(sizeof(int) * 2); 

b、free释放内存

  堆上面的内存大小是固定的,用完就没了,如果此时程序没有结束的话就会报错,即内存泄漏导致的溢出。这在对一些堆内容不大的嵌入式设备上编写程序时,需要特别注意。这时候就在代码末尾释放掉申请的内存就可以。比如释放上面申请的ret可以在代码末尾加上free(ret);。子函数中要返回申请的堆内容的话,是不用释放的,在主函数释放对应的返回值就可以了。

c、strlen求字符数组长度

  c语言中有一些命令可以快捷的用于开发,strlen(char*)可以用来就一个字符数组的大小,只能求字符数组的大小,当然字符串也是字符数组。因此,题目所给的字符数组便可以用该命令来获取数组大小。

//获取字符数组的大小
int s_len = strlen(s);

d、strncpy函数

  该函数的全部描述为:char *strncpy(char *dest, const char *src, size_t n)把 src 所指向的字符串复制到 dest,最多复制 n 个字符。当 src 的长度小于 n 时,dest 的剩余部分将用空字节填充。当我们知道最长回文字串的首地址和长度之后,就可以用这个库函数将其取出,进行return


四、解题代码(附注释)

//返回值为ret指针,ret[0]是回文字长度,ret[1]是首个字在s数组中的位置
int* lenOfPalindrome(char* s, int left, int right){
    int L = left, R = right;
    int* ret = malloc(sizeof(int)*2);
    while(L >= 0 && R <= strlen(s) - 1 && s[L] == s[R]){
        L--;
        R++;
    }
    ret[0] = R - L - 1;//之所以是这样,是因为while循环是先判断后处理,L多减了1,R多加了1
    ret[1] = L + 1;//之所以是这样,是因为while循环是先判断后处理,L多减了1
    return ret;
}

char* longestPalindrome(char* s) {
    if(strlen(s) <= 1) return s;//长度小于等于1,直接返回
    int* len = NULL;

    for(int i = 0; i < strlen(s) - 1; i++){
        int* len1 = lenOfPalindrome(s, i, i);//奇数情况
        int* len2 = lenOfPalindrome(s, i, i+1);//偶数情况
        if(len == NULL || len1[0] > len[0]){
            free(len);
            len = len1;
        } else {
            free(len1);
        }
        if(len == NULL || len2[0] > len[0]){
            free(len);
            len = len2;
        } else {
            free(len2);
        }
    }
    char* result = malloc(sizeof(char) * (len[0] + 1));//要多算一个结束符号位置
    result = strncpy(result, s + len[1], len[0]);
    result[len[0]] = '\0';//要加上结束符
    free(len);
    return result;
}
  • 17
    点赞
  • 6
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值