Longest Palindromic Substring解题心得

Longest Palindromic Substring解题心得

原题描述:https://leetcode.com/problems/longest-palindromic-substring/description/

第一种思路

以每个字母为中心向两端进行匹配

对于最长回文子串问题,我想到的第一种解题思路就是顺序遍历字符串s,以回文子串的中心为目标匹配搜索回文子串

设置中心下标i,设定left,right哨兵,以当前s[i]为中心进行向两端的字母匹配,同时每次比较并记录最大回文子串半径maxR(即子串长度的一半),以及子串的左右位置left,right

  • 坑点:仔细思考下,这样的思路缺少了对偶数长度回文子串的搜索,所以可以进行如下改进
    1. 使i遍历s.size()*2次,每当i遍历到偶数则,以s[i/2]为中心进行回文匹配;当i为奇数时,则设定left=i/2,right=(i+1)/2,从而双向扩张搜索匹配的回文
    2. 为s间隔插入特殊字符,如插入’$‘ 或者‘ ’,匹配得到的最大半径不是实际最长回文子串的半径,而是中间含有特殊字符的字符串,需要另外过滤得到真实值
      这里写图片描述
      这里写图片描述

复杂度分析

  • 时间复杂度
    • 纠正后的算法,设定k为最长子串的半径,n为字符串长度,则时间复杂度为 O(nk) ,最差情况下为 O(n2)
  • 空间复杂度
    • 由于算法只是对字符串进行遍历,对于第一种纠正方法,需要n的空间,第二种则需要2n的空间,于是我们可以得出空间复杂度为 O(n)

第二种思路

利用回文的性质减少重复性搜索

分析发现回文拥有一种特质,即左右的对称性

所以我们以第一种算法的思路为基础进行改良,当我们以i为中心向两边搜索时,已知左边的字母的回文半径,在左边位置left下,回文半径为R[left],

右边字母由于对称性可以知道,只要以left为中心的回文在以flag为中心的回文范围内,即left-(flag-R[flag])>R[left] 或者 (flag+R[flag])-right>R[right]则可以断定R[right]=R[left](注:具体实现需要根据R[flag]的定义形式,判断临界值情况)
这里写图片描述

if (R[j]>=right-i){
    flag=i;
    right++;
    left=2*i-right;
    break;
 }
 else {
    R[i]=R[j];
 }

这样子,当当前flag位置的R[flag]求到后,再对flag为中心的回文子串S[flag]进行检查,同时更新回文右边的R[i],当出现半径长度超过以flag为中心字符串的范围时,更新flag到当前位置flag=right;,进入下一层循环,则flag到right之间的循环可以省略

  • 坑点:千万不要忘记!!!flag更新后,更新right和left时不要直接让right=flag一样的位置;而应该当R[j]超出范围,则right只向右移动一位,同时更新left,保持对称性,这样可以节省很多不必要的重复搜索

代码实现如下:
这里写图片描述

复杂度分析

对于这种算法的时间复杂度分析,本人不才,想法不是特别清晰,意识里猜测是O(n)的时间,具体证明方法未想到

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值