leetcode5. 最长回文子串
作者:互联网
leetcode5. 最长回文子串
1. 题目
给你一个字符串 s,找到 s 中最长的回文子串。
示例 1:
输入:s = “babad”
输出:“bab”
解释:“aba” 同样是符合题意的答案。
示例 2:
输入:s = “cbbd”
输出:“bb”
示例 3:
输入:s = “a”
输出:“a”
示例 4:
输入:s = “ac”
输出:“a”
2. 解答
回文串:如果一个字符串正着读和反着读都是一样的,就是回文串
中心扩展算法:
我们观察到回文中心的两侧互为镜像。因此,回文可以从它的中心展开,并且只有2n-1个这样的中心。
你可能会问,为什么会是 2n - 1 个,而不是 n 个中心?
因为回文的中心要区分单双。
-
假如回文的中心为双数,例如 abba,那么可以划分为 ab bb ba,对于n长度的字符串,这样的划分有 n-1 种。
-
假为回文的中心为单数,例如 abcd, 那么可以划分为 a b c d, 对于n长度的字符串,这样的划分有 n 种。
对于 n 长度的字符串,我们其实不知道它的回文串中心倒底是单数还是双数,所以我们要对这两种情况都做遍历,也就是 n+(n-1) = 2n - 1,所以时间复杂度为 O(n)。
当中心确定后,我们要围绕这个中心来扩展回文,那么最长的回文可能是整个字符串,所以时间复杂度为 O(n)。
所以总时间复杂度为 O(n^2)
// 中心扩展法
#define MAX(a, b) (((a) > (b)) ? (a) :(b))
int expandAroundCenter(char *s, int len, int left, int right) {
int l = left;
int r = right;
while (l >= 0 && r < len && s[l] == s[r]) {
// 计算以left和right为中心的回文串长度
l--;
r++;
}
return r - l - 1;
}
char * longestPalindrome(char * s) {
int len = strlen(s);
if (len <= 1) {
return s;
}
int start = 0;
int end = 0;
int maxLen = 0;
for (int i = 0; i < len; i++) {
int len1 = expandAroundCenter(s, len, i, i); // 一个元素为中心
int len2 = expandAroundCenter(s, len, i, i + 1); // 两个元素为中心
maxLen = MAX(MAX(len1, len2), maxLen);
if (maxLen > end - start + 1) {
start = i - (maxLen - 1) / 2; // 获取回文串起始点位置
end = i + maxLen / 2; // 获取回文串结束点位置
}
}
int index = 0;
char *res = (char *)malloc(sizeof(char) * (maxLen + 1));
for (int i = start; i < start + maxLen; i++) {
res[index++] = s[i];
}
res[index] = '\0';
return res;
}
标签:子串,leetcode5,中心,int,len,char,maxLen,回文 来源: https://blog.csdn.net/yu1500772557/article/details/120187995