【力扣】5. 最长回文子串 - 力扣(LeetCode)

这里主要是记录一些我做这个题遇到的问题及解决办法

1.问题描述

在这里插入图片描述

1.1 思路分析:

  对于个题目而言,我使用的均是中心扩散法,但是细节处理有些不同,有两个版本,一个是字符串原地返回,另外一个是申请内存并进行保持符合要求的字符串,然后进行返回;
  总体而言,就是分为两种情况,而且两种情况均进行遍历,第一种就是类似"abacd"的情况,遍历到b时,以其为中心向两边扩散,直到两边不相等,另外一种是abccbd,那么遍历到第一个c时,就不能以c为中心向两边遍历看看是否相等,也就是偶数情况,这时要把left指向第一个c,把right指向第二c,然后进行判断。
  !!!如果只按照上面的思路进行写程序,会显得很麻烦,很多细节要考虑到,因此可以选择暴力一点,对每一个字符,我们都认为它既是奇数类又是偶数类,对一个字符进行两次遍历,按照奇数遍历一次,按照偶数遍历一次,那么虽然增加了重复度,但是写代码时思路会大大清晰

2.程序代码及注释:

2.1 方法1–申请内存-中心扩散

方法1-申请内存-中心扩散-两种方式均遍历
  一些细节
 首先对于申请的内存: 要进行初始化,而且要有字符串结尾符’\0’,不然会出现堆栈错误的提示,编译不通过;

    char* res = (char*)malloc(sizeof(char) * 10001);
    res[0] = s[0];
    res[1]='\0';
char* longestPalindrome(char* s) {
   int len = strlen(s);
   int i, j, k, left, right, max, flag;
   int ll, rr;
   char mid;
   char* res = (char*)malloc(sizeof(char) * 10001);
   res[0] = s[0];
   res[1]='\0';

   max = 0;
   left = 0;
   right = 0;
   k = 0;
   if (len <= 1) {
       return s;
   }

   for (i = 0; i < len; i++) // 循环遍历完整个字符串,每个字符都要确定一下
   {
   //奇数情况
       left = i - 1;
       right = i + 1;
       while (left >= 0 && right < len && s[left] == s[right]) {
           if (max < (right - left + 1)) {
               max = right - left + 1;
               ll = left;
               rr = right;
           }
           left--;
           right++;
       }
  //偶数情况
       left = i;
       right = i + 1;
       while (left >= 0 && right < len && s[left] == s[right]) {
           if (max < (right - left + 1)) {
               max = right - left + 1;
               ll = left;
               rr = right;
           }
           left--;
           right++;
       }
//把符合要求的值给存储起来
       for (j = ll; j <= rr; j++) {
           res[k] = s[j];
           k++;
           res[k] = '\0';
       }
       k = 0;
   }

   return res;
}

2.1 方法2-中心扩散法+字符串原地返回

方法1-申请内存-中心扩散-两种方式均遍历
  一些细节
 首先对于max = 1;//思考为什么是1?不是0?这个问题比较简单,对于字符串"ab"而言,循环中不会进行判断,也就是max的值不会更新,所以返回s时第二个值要截断成’\0’,所以要max预设成1;
 其次对于s[max] = '\0';//思考为什么是max,不是rr+1,或者right??;这个问题我也是没有发现,首先可以排除right,因为right最大会增加到len,也就是超出了数组的边界,所以先排除right。但是程序中:rr和max是同时增加的,而且数组的长度是[ll,rr]闭区间下标对应的值,所以截断符\0理所当然的截到rr+1,这时很理所当然的,我当时也是这样认为的,但是结果是错误的!

 if (max < (right - left + 1)) 
 {
        max = right - left + 1;//max和rr是同时增加的
        ll = left;
        rr = right;
 }

  错误的原因:
  这个错误的原因是后的语句顺序,首先思想是正确的,但是这时建立在s不变的基础上,但是后面的语句是这样的:

/*错误语句*/
 s = s + ll;//先修改s
 s[rr+1] = '\0';//再截断s

  上面先改变了s的起始位置,然后再截断,这样明显是错误的,实际修改这样就对了:

s[rr+1] = '\0';//先截断s
s = s + ll;//在修改s

  上面的顺序就是正确的。
  而对于max而言,其一直记录的就是整个最大长度,结果都是不发生改变的,其书写顺序应该按照下列这样

s = s + ll;//先修改s
s[max] = '\0';//再截断s

  如果写成这样的顺序就是错误的:

  /*错误语句*/
 s[max] = '\0';//先截断s
 s = s + ll;//再修改s
如果理解不了,可以用一个例制:“cbbd”,当循环结束时,rr=2,ll=1,max=2;
  • 如果先修改s=s+ll,那么说s=“bbd",此时再截断应该使用的是s[max]或者s[rr]
  • 如果先截断s,那么就是s[max+1]=‘\0’,或者s[rr+1]=‘\0’,此时s=“cbb”,然后修改s,也就是s=s+ll;
char* longestPalindrome(char* s) {
   int len = strlen(s);
   int i, j,left, right, max;
   int ll, rr;
   max = 1;//思考为什么是1?不是0?
   left = 0;
   right = 0;
   ll=0;
   rr=0;
   if (len <= 1) {
       return s;
   }

   for (i = 0; i < len; i++) // 循环遍历完整个字符串,每个字符都要确定一下
   {

       left = i - 1;
       right = i + 1;
       while (left >= 0 && right < len && s[left] == s[right]) {
           if (max < (right - left + 1)) {
               max = right - left + 1;
               ll = left;
               rr = right;
           }
           left--;
           right++;
       }

       left = i;
       right = i + 1;
       while (left >= 0 && right < len && s[left] == s[right]) {
           if (max < (right - left + 1)) {
               max = right - left + 1;
               ll = left;
               rr = right;
           }
           left--;
           right++;
       }

   }
   s = s + ll;
   s[max] = '\0';//思考为什么是max,不是rr,或者right??

   return s;
}
  • 5
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
回答: 最长回文子串可以通过两种方法来实现。第一种是使用中心扩展法,代码如下: ```python class Solution: def check(self, s, l, r): while l >= 0 and r < len(s) and s[l == s[r]: l -= 1 r += 1 return l + 1, r - 1 def longestPalindrome(self, s: str) -> str: start, end = 0, 0 for x in range(len(s)): l1, r1 = self.check(s, x, x) l2, r2 = self.check(s, x, x + 1) if r1 - l1 > end - start: start, end = l1, r1 if r2 - l2 > end - start: start, end = l2, r2 return s[start:end+1] ``` 第二种方法是使用动态规划,代码如下: ```python class Solution: def longestPalindrome(self, s: str) -> str: res = '' for i in range(len(s)): start = max(0, i - len(res) - 1) temp = s[start:i+1] if temp == temp[::-1]: res = temp else: temp = temp<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* [5. 最长回文子串(Python 实现)](https://blog.csdn.net/d_l_w_d_l_w/article/details/118861851)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *2* [LeetCode(Python3)5.最长回文子串](https://blog.csdn.net/weixin_52593484/article/details/124718655)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] - *3* [力扣 (LeetCode)刷题笔记5.最长回文子串 python](https://blog.csdn.net/qq_44672855/article/details/115339324)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT0_1"}}] [.reference_item style="max-width: 33.333333333333336%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值