5. 最长回文子串

题目

给你一个字符串 s,找到 s 中最长的回文子串。

示例 1:

输入:s = "babad"

输出:"bab"

解释:"aba" 同样是符合题意的答案。

示例 2:

输入:s = "cbbd"

输出:"bb"

提示:

  • 1 <= s.length <= 1000
  • s 仅由数字和英文字母组成

代码

完整代码

c 复制代码
#include <string.h>
#include <stdbool.h>
#include <stdio.h>
#include <stdlib.h>

bool isHuiwen(char* head, char* tail)
{
    while (head < tail)
    {
        if((*head) != (*tail))
        {
            return false;
        }
        head++;
        tail--;
    }
    return true;
}

char* longestPalindrome(char* s) {
    int len = strlen(s);
    if(len == 1)
    {
        return s;
    }
    char* head = s,*tail = s + (len - 1);
    char* res = (char*)calloc(len + 1, sizeof(char));
    while(head < s + len - 1)
    {
        while(head != tail)
        {
            if(isHuiwen(head, tail))
            {
                if(tail-head+1 > strlen(res))
                {
                    strncpy(res, head, tail-head+1);
                }
            }
            tail--;
        }
        tail = s + (len - 1);
        head++;
    }
    if(strlen(res) == 0)
    {
        strncpy(res, s, 1);
    }
    return res;
}

// int main(void)
// {
//     char a[] = "bb";
//     printf("return %s",longestPalindrome(a));
// }

思路分析

  1. 检查回文 :定义一个函数 isHuiwen 来检查字符串 s 的子串是否为回文。
  2. 遍历字符串 :使用两个指针 headtail 来遍历字符串的所有子串。
  3. 记录最长回文子串:每次找到一个回文子串时,比较其长度并记录最长的那个。

拆解分析

  • 检查回文:通过两个指针从字符串的两端向中间移动,检查字符是否相同。
  • 遍历字符串:从字符串的每一个起点开始,检查从当前起点到终点的所有子串。
  • 记录结果:每次发现新的回文子串,如果其长度大于当前记录的最长回文子串的长度,则更新结果。

复杂度分析

  • 时间复杂度O(n^3),其中 n 是字符串的长度。遍历所有子串需要 O(n^2),每次检查回文需要 O(n)
  • 空间复杂度O(n),需要额外的空间来存储最长回文子串。

结果

O(n^3)恐怖如斯

一题多解

动态规划

动态规划思路分析

  1. 定义状态 :使用二维数组 dp,其中 dp[i][j] 表示子串 s[i...j] 是否为回文。
  2. 状态转移 :如果 s[i] == s[j]dp[i+1][j-1] 为真,则 dp[i][j] 为真。
  3. 初始化 :所有单个字符都是回文,即 dp[i][i] = true
  4. 结果更新:在遍历过程中记录最长的回文子串。

动态规划复杂度分析

  • 时间复杂度O(n^2),遍历所有子串。
  • 空间复杂度O(n^2),使用二维数组存储结果。

动态规划代码

c 复制代码
char* longestPalindrome(char* s) {
    int len = strlen(s);
    if (len < 2) {
        return s;
    }

    int maxLen = 1, start = 0;
    bool dp[1000][1000] = {false};

    for (int i = 0; i < len; i++) {
        dp[i][i] = true;
    }

    for (int j = 1; j < len; j++) {
        for (int i = 0; i < j; i++) {
            if (s[i] == s[j]) {
                if (j - i == 1) {
                    dp[i][j] = true;
                } else {
                    dp[i][j] = dp[i + 1][j - 1];
                }
            } else {
                dp[i][j] = false;
            }

            if (dp[i][j] && j - i + 1 > maxLen) {
                maxLen = j - i + 1;
                start = i;
            }
        }
    }

    char* res = (char*)malloc((maxLen + 1) * sizeof(char));
    strncpy(res, &s[start], maxLen);
    res[maxLen] = '\0';
    return res;
}

结果

中心扩展法

中心扩展法思路分析

  1. 中心扩展:从字符串的每个字符和每两个字符之间作为中心,向两边扩展寻找回文子串。
  2. 记录结果:在扩展过程中记录最长的回文子串。

中心扩展法复杂度分析

  • 时间复杂度O(n^2),每个字符都需要进行扩展。
  • 空间复杂度O(1),只使用常数级别的额外空间。

中心扩展法代码

c 复制代码
char* longestPalindrome(char* s) {
    int len = strlen(s);
    if (len < 2) {
        return s;
    }

    int maxLen = 1, start = 0;
    
    for (int i = 0; i < len; i++) {
        int l = i, r = i;
        while (l >= 0 && r < len && s[l] == s[r]) {
            if (r - l + 1 > maxLen) {
                maxLen = r - l + 1;
                start = l;
            }
            l--;
            r++;
        }

        l = i, r = i + 1;
        while (l >= 0 && r < len && s[l] == s[r]) {
            if (r - l + 1 > maxLen) {
                maxLen = r - l + 1;
                start = l;
            }
            l--;
            r++;
        }
    }

    char* res = (char*)malloc((maxLen + 1) * sizeof(char));
    strncpy(res, &s[start], maxLen);
    res[maxLen] = '\0';
    return res;
}

结果

相关推荐
handsomezqh6 分钟前
洛谷U611548 助教的比拼
c++·算法
小李小李快乐不已7 分钟前
图论理论基础(4)
c++·算法·图论·迭代加深
好易学·数据结构13 分钟前
可视化图解算法72:斐波那契数列
数据结构·算法·leetcode·动态规划·力扣·牛客网
楼田莉子30 分钟前
基于Linux的个人制作的文件库+标准输出和标准错误
linux·c语言·c++·学习·vim
数据门徒30 分钟前
《人工智能现代方法(第4版)》 第6章 约束满足问题 学习笔记
人工智能·笔记·学习·算法
FPGA_无线通信34 分钟前
OFDM 频偏补偿和相位跟踪(1)
算法·fpga开发
数据门徒1 小时前
《人工智能现代方法(第4版)》 第8章 一阶逻辑 学习笔记
人工智能·笔记·学习·算法
风止何安啊1 小时前
递归 VS 动态规划:从 “无限套娃计算器” 到 “积木式解题神器”
前端·javascript·算法
踢球的打工仔1 小时前
前端html(2)
前端·算法·html
CoderYanger1 小时前
动态规划算法-子数组、子串系列(数组中连续的一段):21.乘积最大子数组
开发语言·算法·leetcode·职场和发展·动态规划·1024程序员节