IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 数据结构与算法 -> 【leetcode】【5】最长回文子串 -> 正文阅读

[数据结构与算法]【leetcode】【5】最长回文子串

最长回文子串

题目

给你一个字符串s,找到s中最长的回文子串。
** 回文子串指 abcba 等对称结构的字符串。

题解1:动态规划(Dynamic Programming)

思路源自程序员Carl,他在Github上创建了名为力扣刷题攻略的项目,链接贴在文末。

Carl在题解中提及了动规五部曲:

  1. 确定dp数组以及下标的含义。
  2. 确定递推公式。
  3. dp数组如何初始化。
  4. 确定遍历顺序。
  5. 举例推导dp数组。

在实际解决动规问题时,可以通过上述步骤为自己提供一个比较清晰的思路,接下来将详细阐述本题中每个步骤需要考虑的内容。

1.确定dp数组以及下标的含义

本题中将动规数组声明为布尔类型的二维数组,其中下标为 i、j 的元素表示字符串 s 从下标 i 至下标 j 之间的子串是否为回文子串。

2.确定递推公式

寻找当前元素与值已知的元素之间的联系,是推导递推公式的关键。
假定 i、j 为子串的头元素与尾元素的下标,探究该子串是否为回文串,实际可能的情况有以下几种:

  1. s[i] ≠ s[j]:毋庸置疑该子串不是回文串;
  2. s[i] == s[j]:这种情况要分点讨论:
    ①若 i == j,则s[i]与s[j]为同一元素,必然为回文串;
    ②若 i == j - 1,必然为回文串;
    ③若 j - i > 1,则【i,j】区间的子串是否为回文串需要看【i + 1,j - 1】区间的子串是否为回文串。

这部分判断逻辑的代码实现如下:

if(s[i] == s[j] && (j - i <= 1 || dp[i + 1, j - 1] == 1))
{
	dp[i, j] = 1;
    if(j - i + 1 > maxLength)
	{
		maxLength = j - i + 1;
		left = i;
	}
}

3.dp数组如何初始化

因为 dp【i,j】代表了区间【i,j】之间的子串是否为回文串,所以初始化值为0,代表着false;在验证了子串为回文串才重新赋值为1,代表true。

4.确定遍历顺序

dp【i,j】的值由dp【i + 1,j - 1】推导,后者位于前者的左下方位置,所以遍历顺序有以下两种:①以行为主,行从大往小遍历,列从左往右遍历;②以列为主,列从左往右遍历,行从上往下遍历。

5.举例推导dp数组

实际问题中多举例验证即可。

代码部分

时间复杂度O(n2),空间复杂度O(n2

public class Solution {   
    public string LongestPalindrome(string s) {
        int left = 0;
        int maxLength = 0;
        int[,] dp = new int[s.Length, s.Length];

        for(int j = 0; j < s.Length; j++)
            for(int i = 0; i <= j; i++)
            {
                if(s[i] == s[j] && (j - i <= 1 || dp[i + 1, j - 1] == 1))
                {
                    dp[i, j] = 1;
                    if(j - i + 1 > maxLength)
                    {
                        maxLength = j - i + 1;
                        left = i;
                    }
                } 
            }
        
        return s.Substring(left, maxLength);
    }
}

题解2:双指针

首先要考虑两件事:①枚举所有可能的子串;②判断子串是否为回文串。
如何判断子串是否为回文串?回文串的特点是关于中心呈两端对称,中心可以是长度为一或长度为二的回文串,单个字符毋庸置疑是回文串,长度为二的情况下需要两个字符相等的字符串才符合条件。对字符串s中的每一个字符进行遍历,单次操作考虑以上两种情况,从选定的中心点每次往两边扩展一个单位的字符,根据比对结果决定是否继续扩展,即可将所有可能的子串都纳入考虑范围。以下是双指针思路下的C#解题代码:
时间复杂度:O(n2),空间复杂度:O(1);

public class Solution {   
    int left = 0;
    int maxLength = 1;
    
    public string LongestPalindrome(string s) {
        for(int i = 0; i < s.Length - 1; i++)
        {
            FindPalindrome(s, i, i);
            FindPalindrome(s, i, i + 1);
        }
        
        return s.Substring(left, maxLength);
    }

    public void FindPalindrome(string s, int l, int r)
    {
        while(l >= 0 && r < s.Length && s[l] == s[r])
        {
            if(maxLength < r - l + 1)
            {
                maxLength = r - l + 1;
                left = l;
            }
            l--;    r++;
        }
    }
}

文末

力扣刷题攻略

  数据结构与算法 最新文章
【力扣106】 从中序与后续遍历序列构造二叉
leetcode 322 零钱兑换
哈希的应用:海量数据处理
动态规划|最短Hamilton路径
华为机试_HJ41 称砝码【中等】【menset】【
【C与数据结构】——寒假提高每日练习Day1
基础算法——堆排序
2023王道数据结构线性表--单链表课后习题部
LeetCode 之 反转链表的一部分
【题解】lintcode必刷50题<有效的括号序列
上一篇文章      下一篇文章      查看所有文章
加:2021-09-29 10:33:19  更:2021-09-29 10:35:09 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:56:08-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码