【LeetCode】P5 最长回文子串(未完结)

P5 最长回文子串

题目链接:5. 最长回文子串.

题目描述

给定一个字符串 s,找到 s 中最长的回文子串。你可以假设 s 的最大长度为 1000。

示例:

输入: “babad”
输出: “bab”
注意: “aba” 也是一个有效答案。

输入: “cbbd”
输出: “bb”

题解

方法一:暴力算法

思路

枚举出所有长度大于 1 的子串,逐个检验它们是否为回文子串,并找到最长回文子串。

算法

class Solution {
public:
	string longestPalindrome(string s) {
		int size=s.size();
		int target=0;				//标记最长回文子串的起始位置
		int maxLen=1;				//记录最长回文子串长度,单个字符为一个回文子串
		for(int begin=0;begin<=size-2;++begin){
			for(int end=begin+1;end<size;++end){
				if(end-begin+1>maxLen&&isPalindrome(s,begin,end)){
					maxLen=end-begin+1;
					target=begin;
				}
			}
		}
		return s.substr(target,maxLen);
	}

	bool isPalindrome(string s,int begin,int end){
		while(end>begin){
			if(s[begin]!=s[end]){
				return false;
			}
			++begin;
			--end;
		}
		return true;
	}
};

复杂度分析

假设 n n n 表示字符串 s s s 的长度

  • 时间复杂度: O ( n 3 ) O(n^3) O(n3),因为枚举出所有长度大于 1 的子串的时间复杂度为 O ( n 2 ) O(n^2) O(n2),而还要对每个子串进行检验是否为回文串,检验一个子串的时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

方法二:中心扩散法

思路

回文子串的长度可以为奇数也可以为偶数,长度为奇数的回文子串的中心位置为 1 个字符,长度为偶数的回文子串的中心位置为 2 个字符。

在这里插入图片描述
中心扩散法,顾名思义,在字符串 s s s 中,我们可以先以 1 个字符为回文串的中心位置,往两边扩散来寻找长度为奇数的回文子串;以连续的 2 个字符为回文串的中心位置,往两边扩散来寻找长度为偶数的回文子串。

算法

伪代码:

  • for(int i=0;i<=size-2;++i)
    • i 为中心位置,往两边扩散来寻找长度为奇数的回文子串
    • ii+1 为中心位置,往两边扩散来寻找长度为偶数的回文子串
    • 记录最长回文子串长度 maxLen,以及最长回文子串的中心位置 target(若最长回文子串的长度为偶数,target 为靠左的中心字符的位置)
  • 返回以第 target-(maxLen-1)/2 (关于这个式子,下面有推导过程)个字符为开头,长度为 maxLen 的子串
    在这里插入图片描述
    由于是整型运算,向下取整,长度为偶数的回文子串的起始位置的计算中,maxLen 为偶数,所以 target-(maxLen-2)/2 = target-(maxLen-1)/2,这样就与长度为奇数的回文子串的起始位置的计算合并为一种情况。
class Solution {
public:
	string longestPalindrome(string s) {
		int size=s.size();
		int target=0;				//标记最长回文子串的中心位置
		int maxLen=1;				//记录最长回文子串长度,单个字符为一个回文子串
		for(int i=0;i<=size-2;++i){
			int oddLen=centerSpread(s,i,i);		//寻找长度为奇数的回文子串,中心字符为i
			int evenLen=centerSpread(s,i,i+1);	//寻找长度为偶数的回文子串,中心字符为i、i+1
			if(max(oddLen,evenLen)>maxLen){
				maxLen=max(oddLen,evenLen);
				target=i;
			}
		}
		return s.substr(target-(maxLen-1)/2,maxLen);
	}

	int centerSpread(string s,int begin,int end){
		int size=s.size();
		while(0<=begin&&end<size){
			if(s[begin]!=s[end]){
				break;
			}
			--begin;
			++end;
		}
		return end-begin-1;
	}
};

复杂度分析

假设 n n n 表示字符串 s s s 的长度

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2),只需要枚举出中心位置,共 2 ( n − 1 ) 2(n-1) 2(n1) 次,在每次扩散中,时间复杂度为 O ( n ) O(n) O(n)
  • 空间复杂度: O ( 1 ) O(1) O(1)

方法三:动态规划

思路

算法

复杂度分析

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值