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. 遍历字符串 :使用两个指针 head 和 tail 来遍历字符串的所有子串。
  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;
}

结果

相关推荐
垆边人似月.7 分钟前
华为机试题 :有效的括号
c++·算法·华为
奋斗的阿狸_198622 分钟前
ESP32-S3 + ES7210 四通道麦克风录音上传方案
c语言·开发语言·fpga开发
2401_8628808238 分钟前
iMX6ULL 驱动工程搭建 + LED 灯驱动
c语言·驱动开发·嵌入式硬件
A加ITIL教练长河achotsao43 分钟前
ITIL Master 战略领导者课后系列分享:AI编程正在重新划分研发与运维的边界
算法
hahaha601644 分钟前
FPGA+ARM实现AWB的全流程
人工智能·嵌入式硬件·算法·计算机视觉·fpga开发
李洱1 小时前
LangChain 和 LangGraph 的区别:核心原理与使用场景
算法
夏幻灵1 小时前
每日一题:LeetCode 206:反转链表——三指针与原地反转详解
算法·leetcode·链表
ACP广源盛139246256731 小时前
Type‑C 扩展坞方案选型笔记|国产 DP1.4 转 HDMI2.0 桥接芯片 GSV2201S @ACP评估
c语言·开发语言·笔记·硬件架构·硬件工程·国产芯片
CQU_JIAKE1 小时前
10.9【A】
数据结构