【算法与数据结构】647、516、LeetCode回文子串+最长回文子序列

文章目录

  • 一、647、回文子串
  • 二、516、最长回文子序列
  • 三、完整代码

所有的LeetCode题解索引,可以看这篇文章——【算法和数据结构】LeetCode题解。

一、647、回文子串

在这里插入图片描述

  思路分析:判断一个字符串是否为回文串那么必须确定回文串的所在区间,而一维数组无法描述区间,因此我们需要用一个二维的dp数组来表示。我们只需要统计dp数组中回文串的个数即可。

  1. 第一步,动态数组的含义。 d p [ i ] [ j ] dp[i][j] dp[i][j]代表区间 [ i , j ] [i, j] [i,j](左闭右闭)的字符串是否为回文串。dp数组的类型为bool类型。
  2. 第二步,递推公式。 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由两种情况推导出来:
  • s [ i ] s[i] s[i] s [ j ] s[j] s[j]相等:若 i = j i = j i=j,仅一个字符(例如a),那么必然是回文串;若 j − i = 1 j - i = 1 ji=1,两个字符(例如aa),那么也是回文串;剩下的情况: [ i , j ] [i, j] [i,j]的字符串是否为回文串与 [ i + 1 , j − 1 ] [i + 1, j - 1] [i+1,j1]的字符串是否为回文串相同,即 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] dp[i][j] = dp[i + 1][j - 1] dp[i][j]=dp[i+1][j1]
  • s [ i ] s[i] s[i] s [ j ] s[j] s[j]不相等:那么 d p [ i ] [ j ] = f a l s e dp[i][j] = false dp[i][j]=false
	if (s[i] == s[j]) {if (j - i <= 1 || dp[i + 1][j - 1]) {result++;dp[i][j] = true;}}else dp[i][j] = false;
  1. 第三步,元素初始化。所有元素全部假设为false。
	vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));
  1. 第四步,递归顺序。从递归公式 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] dp[i][j] = dp[i + 1][j - 1] dp[i][j]=dp[i+1][j1]中可以看出, d p [ i ] [ j ] dp[i][j] dp[i][j]需要反对角线上的元素。因此我们需要先让最下面一行的元素先有结果。同时,按定义来说 d p [ i ] [ j ] dp[i][j] dp[i][j]是一个对称句矩阵,循环只要覆盖主对角线及其上方的元素即可(如图所示)。
  2. 第五步,打印结果。

在这里插入图片描述

  程序如下

// 647、回文子串-动态规划
class Solution {
public:int countSubstrings(string s) {vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));int result = 0;for (int i = s.size() - 1; i >= 0; i--) {	// 从下往上行遍历for (int j = i; j < s.size(); j++) {	// 从前往后列遍历if ((s[i] == s[j]) && (j - i <= 1 || dp[i + 1][j - 1])) {result++;dp[i][j] = true;}}}return result;}
};

复杂度分析:

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n 2 ) O(n^2) O(n2)

二、516、最长回文子序列

在这里插入图片描述

  思路分析:本题的分析思路和647题差不多。

  1. 第一步,动态数组的含义。 d p [ i ] [ j ] dp[i][j] dp[i][j]代表区间 [ i , j ] [i, j] [i,j](左闭右闭)的字符串的最大回文串长度。
  2. 第二步,递推公式。 d p [ i ] [ j ] dp[i][j] dp[i][j]可以由两种情况推导出来:
  • s [ i ] s[i] s[i] s [ j ] s[j] s[j]相等:那么 d p [ i ] [ j ] = d p [ i + 1 ] [ j − 1 ] + 2 dp[i][j] = dp[i + 1][j - 1] + 2 dp[i][j]=dp[i+1][j1]+2
  • s [ i ] s[i] s[i] s [ j ] s[j] s[j]不相等:那么说明加入 s [ i ] s[i] s[i] s [ j ] s[j] s[j]不能使回文串长度增加。那么单独加入 s [ i ] s[i] s[i] s [ j ] s[j] s[j]看看那个能组成最长的回文子序列,加入 s [ i ] s[i] s[i]的回文子序列长度为 d p [ i ] [ j − 1 ] dp[i][j-1] dp[i][j1],加入 s [ j ] s[j] s[j]的回文子序列长度为 d p [ i + 1 ] [ j ] dp[i+1][j] dp[i+1][j],二者取大值,即 d p [ i ] [ j ] = m a x ( d p [ i ] [ j − 1 ] , d p [ i + 1 ] [ j ] ) dp[i][j] = max(dp[i][j-1], dp[i+1][j]) dp[i][j]=max(dp[i][j1],dp[i+1][j])
	if (s[i] == s[j]) {dp[i][j] = dp[i + 1][j - 1] + 2;}else {dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);}
  1. 第三步,元素初始化。 i = j i = j i=j的一个字符串就是回文串,其他情况的dp数组元素全部初始化为0。
	vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), 0));for (int i = 0; i < s.size(); i++) dp[i][i] = 1;
  1. 第四步,递归顺序。 d p [ i ] [ j ] dp[i][j] dp[i][j]依赖于 d p [ i + 1 ] [ j − 1 ] dp[i + 1][j - 1] dp[i+1][j1] d p [ i + 1 ] [ j ] dp[i + 1][j] dp[i+1][j] d p [ i ] [ j − 1 ] dp[i][j - 1] dp[i][j1]。那么递归顺序需要从下往上,从前往后递归。
  2. 第五步,打印结果。

在这里插入图片描述

  程序如下

// 516、最长回文子序列-动态规划
class Solution2 {
public:int longestPalindromeSubseq(string s) {vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));for (int i = 0; i < s.size(); i++) dp[i][i] = 1;for (int i = s.size() - 1; i >= 0; i--) {	// 从下往上行遍历for (int j = i + 1; j < s.size(); j++) {	// 从前往后列遍历if (s[i] == s[j])	dp[i][j] = dp[i + 1][j - 1] + 2;else				dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);}}return dp[0][s.size() - 1];}
};

复杂度分析:

  • 时间复杂度: O ( n 2 ) O(n^2) O(n2)
  • 空间复杂度: O ( n 2 ) O(n^2) O(n2)

三、完整代码

# include <iostream>
# include <vector>
# include <string>
using namespace std;// 647、回文子串-动态规划
class Solution {
public:int countSubstrings(string s) {vector<vector<bool>> dp(s.size(), vector<bool>(s.size(), false));int result = 0;for (int i = s.size() - 1; i >= 0; i--) {	// 从下往上行遍历for (int j = i; j < s.size(); j++) {	// 从前往后列遍历if ((s[i] == s[j]) && (j - i <= 1 || dp[i + 1][j - 1])) {result++;dp[i][j] = true;}}}return result;}
};// 516、最长回文子序列-动态规划
class Solution2 {
public:int longestPalindromeSubseq(string s) {vector<vector<int>> dp(s.size(), vector<int>(s.size(), 0));for (int i = 0; i < s.size(); i++) dp[i][i] = 1;for (int i = s.size() - 1; i >= 0; i--) {	// 从下往上行遍历for (int j = i + 1; j < s.size(); j++) {	// 从前往后列遍历if (s[i] == s[j])	dp[i][j] = dp[i + 1][j - 1] + 2;else				dp[i][j] = max(dp[i][j - 1], dp[i + 1][j]);}}return dp[0][s.size() - 1];}
};int main() {//string s = "aaa";	// 测试案例//Solution s1;//int result = s1.countSubstrings(s);string s = "bbbab";Solution2 s1;int result = s1.longestPalindromeSubseq(s);cout << result << endl;system("pause");return 0;
}

end

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/453526.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

Quartus IP 之mif与hex文件创建与使用

一、mif与hex概述 ROM IP的数据需要满足断电不丢失的要求&#xff0c;ROM IP数据的文件格式一般有三种文件格式&#xff1a;.mif、.hex、.coe&#xff0c;Xilinx与Intel Altera支持的ROM IP数据文件格式如下&#xff1a; Xilinx与Altera支持的ROM文件格式 Alterahex、mifAM&am…

Java实现婚恋交友网站 JAVA+Vue+SpringBoot+MySQL

目录 一、摘要1.1 项目介绍1.2 项目录屏 二、功能模块2.1 数据中心模块2.2 会员管理模块2.3 新闻管理模块2.4 相亲大会管理模块2.5 留言管理模块 三、系统设计3.1 用例设计3.2 数据库设计3.2.1 会员信息表3.2.2 新闻表3.2.3 相亲大会表3.2.4 留言表 四、系统展示五、核心代码5.…

2.4日总结

第一题&#xff1a;选数 题解&#xff1a;思路还是很简单的&#xff0c;只需要想清楚dfs里的函数都是什么就可以了&#xff0c;还有一个简单的判断素数的函数&#xff0c;这题真没啥难度&#xff0c;就是属于基础题吧&#xff0c;请看AC代码 #include <stdio.h> #includ…

「Kafka」消费者篇

「Kafka」消费者篇 Kafka 消费方式 Kafka 消费者工作流程 消费者总体工作流程 新版本&#xff08;0.9之后&#xff09;的 offset 保存在 kafka 的 Topic 里&#xff0c;持久化到磁盘&#xff0c;可靠性有保障。 老版本&#xff08;0.9之前&#xff09;的 offset 保存在 Zook…

前端学习第4天

一、复合选择器 1.后代选择器 2.子代选择器 3.并集选择器 4.交集选择器 5.伪类选择器 1.伪类-超链接&#xff08;拓展&#xff09; 二、CSS特性 1.继承性 body放在style中 2.层叠性 3.优先级 属性 !important;&#xff08;最高优先级&#xff09; 1.优先级-叠加计算规则 2.em…

源码梳理(3)MybatisPlus启动流程

文章目录 1&#xff0c;MybatisPlus的使用示例2&#xff0c;BaseMapper方法的执行2,1 MybatisMapperProxy代理对象2.2 InvocationHandler接口&#xff08;JDK动态代理&#xff09;2.3 MapperMethodInvoker接口2.4 MybatisMapperMethod 3&#xff0c;SqlSession的执行流程3.1 Sq…

Java SPI 代码示例

Java Service Provider Interface 是JDK自带的服务提供者接口又叫服务发现机制更是一种面向接口的设计思想。即JDK本身提供接口类&#xff0c; 第三方实现其接口&#xff0c;并作为jar包或其他方式注入到其中&#xff0c; 在运行时会被JDK ServiceLoader 发现并加载&#xff0c…

力扣热门100题刷题笔记 - 10. 正则表达式匹配

力扣热门100题 - 10. 正则表达式匹配 题目链接&#xff1a;10. 正则表达式匹配 题目描述&#xff1a; 给你一个字符串 s 和一个字符规律 p&#xff0c;请你来实现一个支持 . 和 * 的正则表达式匹配。 . 匹配任意单个字符 * 匹配零个或多个前面的那一个元素 所谓匹配&#xff…

3.0 Hadoop 概念

本章着重介绍 Hadoop 中的概念和组成部分&#xff0c;属于理论章节。如果你比较着急可以跳过。但作者不建议跳过&#xff0c;因为它与后面的章节息息相关。 Hadoop 整体设计 Hadoop 框架是用于计算机集群大数据处理的框架&#xff0c;所以它必须是一个可以部署在多台计算机上…

Linux内存管理:(十二)Linux 5.0内核新增的反碎片优化

文章说明&#xff1a; Linux内核版本&#xff1a;5.0 架构&#xff1a;ARM64 参考资料及图片来源&#xff1a;《奔跑吧Linux内核》 Linux 5.0内核源码注释仓库地址&#xff1a; zhangzihengya/LinuxSourceCode_v5.0_study (github.com) 外碎片化发生时&#xff0c;页面分配…

2024-2-4-复习作业

源代码&#xff1a; #include <stdio.h> #include <stdlib.h> typedef int datatype; typedef struct Node {datatype data;struct Node *next;struct Node *prev; }*DoubleLinkList;DoubleLinkList create() {DoubleLinkList s(DoubleLinkList)malloc(sizeof(st…

PgSQL技术内幕 - case when表达式实现机制

PgSQL技术内幕 - case when表达式实现机制 CASE表达式如同 C语言中的if/else语句一样&#xff0c;为SQL添加了条件逻辑处理能力&#xff0c;可以根据不同条件返回不同结果。PgSQL支持两种语法&#xff1a;简单表达式和搜索表达式。 1、搜索表达式 语法如下&#xff1a; CASE WH…