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

news2024/11/26 23:32:57

文章目录

  • 一、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.coloradmin.cn/o/1433229.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

安卓平台valgrind交叉编译

背景 通过上次的文章valgrind跨平台调试及其问题分析,为同事们在大部分平台下进行内存问题分析提供了帮助。但是也遇到了阻塞情况&#xff1a;android 平台&#xff0c;无法交叉编译通过。大家对于编译这件事&#xff0c;似乎天然有一种排斥&#xff0c;本能的拒绝&#xff0c…

全网最详细解法|同济大学|高等数学|第八版|习题1-2

文章目录 同济大学&#xff5c;高等数学&#xff5c;第八版&#xff5c;习题1-2&#xff5c;2.1同济大学&#xff5c;高等数学&#xff5c;第八版&#xff5c;习题1-2&#xff5c;2.2同济大学&#xff5c;高等数学&#xff5c;第八版&#xff5c;习题1-2&#xff5c;2.3同济大学…

[Android] 240204批量生成联系人,短信,通话记录的APK

平常在做测试的时候&#xff0c;需要批量生成很多测试数据&#xff1b; 陌生人 联系人名字的生成支持随机生成&#xff0c;也可以自定义生成&#xff0c;自定义生成陌生人的数据&#xff0c;联系人的名字是否带索引&#xff1b; 通话记录 随机生成通话记录&#xff0c;在生…

Cannot resolve plugin org.apache.maven.plugins:maven-compiler-plugin:3.8.1

目录 【问题描述】maven环境报错 Cannot resolve plugin org.apache.maven.plugins:maven-compiler-plugin:3.8.1 【解决办法】 检查maven路径是否一致 路径一致的话&#xff0c;更改配置文件settings.xml的镜像源。 添加代码到 <mirrors> <!-- 阿里镜像 --> &l…

LLaMA 模型中的Transformer架构变化

目录 1. 前置层归一化&#xff08;Pre-normalization&#xff09; 2. RMSNorm 归一化函数 3. SwiGLU 激活函数 4. 旋转位置嵌入&#xff08;RoPE&#xff09; 5. 注意力机制优化 6. Group Query Attention 7. 模型规模和训练超参数 8. 分布式模型训练 前置归一化与后置…

如何使用第三方API采集电商数据呢?

电商商家最常唠叨的就是店铺运营难做。每日多平台店铺数据统计汇总繁琐耗时&#xff0c;人工效率偏低&#xff0c;且工作内容有限。 特别是眼下“618&#xff0c;双十一&#xff0c;双十二&#xff0c;年底大促”将至&#xff0c;如何提高运营的效率和质量、保证产品及服务的良…

单片机的50个电路

单片机 电源 声音模块 收音机 485 蓝牙 光耦 can 光敏电阻 单片机 矩阵 单片机电路 时钟 ADC 接口电路 红外发射 显示模块 红外接收 蜂鸣器驱动 流水灯 usb供电 烧录电路 数码管 EEPROM LCD1602电路 数码管 max485 红外开关 译码器 移位寄存器 步进电机控制 复位电路 下载电路 …

普渡机器人CEO预测2024年服务机器人市场将扩大

原创 | 文 BFT机器人 根据普渡科技有限公司的报告&#xff0c;商用服务机器人在东亚地区的应用比其他地方更为广泛。然而&#xff0c;预计到2024年&#xff0c;全球其他地区也将迎头赶上。这家总部位于中国深圳的公司自豪地宣称&#xff0c;它已经成为中国最大的此类机器人出口…

SpringCloud + Nacos环境下抽取Feign独立模块并支持MultipartFile

文章目录 一、前提条件和背景1. 前提2. 背景 二、Feign模块1. 依赖引入2. application.yaml配置3. 扩展支持MultipartFile4. 将media-api注册到feign 三、Media模块四、Content模块1. 引入依赖2. 启用FeignClient3. 测试 五、需要澄清的几点 一、前提条件和背景 1. 前提 已经…

JQL语法及Python查询 Jira issue信息

文章目录 一、JQL语法1.1 JQL语法简介1.2 Jira中常用的JQL搜索语句 二、查询issue信息2.1 安装JIRA依赖库2.2 登录JIRA2.3 查询JIRA的project信息2.4 查询JIRA的issue信息2.5 搜索Jira issue 一、JQL语法 1.1 JQL语法简介 JIRA 的 JQL 语法由以下几个元素组成&#xff1a; f…

docker-compose部署laravel项目实战(主机nginx连接项目容器)(详细配置过程)

我用的是主机上的nginx,没有用docker安装nginx&#xff0c; 所以需要先在主机上安装nginx # 更新系统yum sudo yum update# 安装安装包sudo yum install epel-release sudo yum install wget# 安装Nginx sudo yum install nginx #启动 sudo systemctl start nginx #开机自启动…

leetcode (算法)66.加一(python版)

需求 给定一个由 整数 组成的 非空 数组所表示的非负整数&#xff0c;在该数的基础上加一。 最高位数字存放在数组的首位&#xff0c; 数组中每个元素只存储单个数字。 你可以假设除了整数 0 之外&#xff0c;这个整数不会以零开头。 示例 1&#xff1a; 输入&#xff1a;digi…

Mocaverse NFT 概览与数据分析

作者&#xff1a;stellafootprint.network 编译&#xff1a;mingfootprint.network 数据源&#xff1a;Mocaverse NFT Collection Dashboard Mocaverse 是 Animoca Brands 推出的专属 NFT&#xff08;非同质化代币&#xff09;系列&#xff0c;包含 8,888 个独特的 "M…

搜索专项---Flood Fill

文章目录 池塘计数城堡问题山峰与山谷 一、池塘计数OJ链接 1.BFS做法 #include <bits/stdc.h>#define x first #define y secondtypedef std::pair<int,int> PII;constexpr int N1010;int n,m; char g[N][N]; bool st[N][N];//用来表示已经记录过的 std::queue&…

matlab使用jdbc连接数据库

1、打包jdbc 2、在matlab安装目录下&#xff0c;进去toolbox目录下&#xff0c;新建一个对应放jdbc包的文件夹&#xff0c;加入放入的是mysql的jdbc驱动包&#xff0c;就新建一个mysql目录&#xff0c;将驱动包放入mysql目录下 3、在toolbox目录下&#xff0c;找到local目录&a…

李沐《动手学深度学习》循环神经网络 经典网络模型

系列文章 李沐《动手学深度学习》预备知识 张量操作及数据处理 李沐《动手学深度学习》预备知识 线性代数及微积分 李沐《动手学深度学习》线性神经网络 线性回归 李沐《动手学深度学习》线性神经网络 softmax回归 李沐《动手学深度学习》多层感知机 模型概念和代码实现 李沐《…

Linux进程信号(2)--信号的保存

目录 1.阻塞信号 1.1 信号其他相关常见概念 1.实际执行信号的处理动作称为信号递达(Delivery&#xff09; 2.信号从产生到递达之间的状态,称为信号未决(Pending)。 3.进程可以选择阻塞 (Block )某个信号。 1.2信号在内核中的表示 sigset_t 信号集操作函数 使用sigprocm…

ReactNative实现弧形拖动条

我们直接看效果 先看下面的使用代码 <CircularSlider5step{2}min{0}max{100}radius{100}value{30}onComplete{(changeValue: number) > this.handleEmailSbp(changeValue)}onChange{(changeValue: number) > this.handleEmailDpd(changeValue)}contentContainerStyle{…

MicroPython ESP32开发:通过寄存器直接访问外围设备

可以通过直接读写寄存器来控制 ESP32 的外设。这就需要阅读数据手册&#xff0c;了解要使用哪些寄存器以及要写入哪些值。下面的示例展示了如何打开和更改 MCPWM0 外设的预分频器。 from micropython import const from machine import mem32# Define the register addresses …

SpringBoot中数据库的连接及Mybatis的配置和使用

目录 1 在pom.xml中引入相关依赖 2 对数据库进行配置 2.1 配置application.yml 2.2 idea连接数据库 (3.2.1有用到) 3 Mybatis的使用 3.1 测试文件的引入 3.2 使用 3.2.1 使用注解(有小技巧(✪ω✪)) 3.2.2 使用动态sql 1 在pom.xml中引入相关依赖 <dependencies&g…