【动态规划】【记忆化搜索】【回文】1312让字符串成为回文串的最少插入次数

本文主要是介绍【动态规划】【记忆化搜索】【回文】1312让字符串成为回文串的最少插入次数,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

作者推荐

【动态规划】【字符串】【表达式】2019. 解出数学表达式的学生分数

本文涉及知识点

动态规划汇总
记忆化搜索 回文 字符串

LeetCode1312. 让字符串成为回文串的最少插入次数

给你一个字符串 s ,每一次操作你都可以在字符串的任意位置插入任意字符。
请你返回让 s 成为回文串的 最少操作次数 。
「回文串」是正读和反读都相同的字符串。
示例 1:
输入:s = “zzazz”
输出:0
解释:字符串 “zzazz” 已经是回文串了,所以不需要做任何插入操作。
示例 2:
输入:s = “mbadm”
输出:2
解释:字符串可变为 “mbdadbm” 或者 “mdbabdm” 。
示例 3:
输入:s = “leetcode”
输出:5
解释:插入 5 个字符后字符串变为 “leetcodocteel” 。
提示:
1 <= s.length <= 500
s 中所有字符都是小写字母。

动态规划

动态规划的状态表示

dp[left][r] 表示s[left,r]变成回文需要插入的字符数。

动态规划的转移方程

d p [ l e f t ] [ r ] = m i n { d p [ l e f t + 1 ] [ r − 1 ] s [ l e f t ] = = s [ r ] d p [ l e f t + 1 ] [ r ] + 1 d p [ l e f t ] [ r − 1 ] + 1 dp[left][r]=min\begin{cases} dp[left+1][r-1] & s[left]==s[r] \\ dp[left+1][r]+1 & \\ dp[left][r-1]+1 & \\ \end{cases} dp[left][r]=min dp[left+1][r1]dp[left+1][r]+1dp[left][r1]+1s[left]==s[r]
用Cal函数代替dp向量:一,方便记忆。二,方便处理left > r。

动态规划的初始值

全为-1,表示未处理。

动态规划的填表顺序

递归计算dp[0][n-1]

动态规划的返回值

dp[0][n-1]

代码

核心代码

class Solution {
public:int minInsertions(string s) {const int n = s.length();vector<vector<int>> dp(n, vector<int>(n, -1));return Cal(dp,s,0, n - 1);}int Cal (vector<vector<int>>& dp ,const string& s,int left, int r){if (left > r){return 0;}if (-1 != dp[left][r]){return dp[left][r];}if (s[left] == s[r]){return dp[left][r] = Cal(dp,s,left + 1, r - 1);}return dp[left][r] = min(Cal(dp, s, left + 1, r) + 1, Cal(dp, s, left, r - 1) + 1);};
};

测试用例

template<class T>
void Assert(const T& t1, const T& t2)
{assert(t1 == t2);
}template<class T>
void Assert(const vector<T>& v1, const vector<T>& v2)
{if (v1.size() != v2.size()){assert(false);return;}for (int i = 0; i < v1.size(); i++){Assert(v1[i], v2[i]);}}int main()
{	string s;{Solution sln;s = "zzazz";auto res = sln.minInsertions(s);Assert(0, res);}{Solution sln;s = "mbadm";auto res = sln.minInsertions(s);Assert(2, res);}{Solution sln;s = "leetcode";auto res = sln.minInsertions(s);Assert(5, res);}
}

2023年2月第一版

class Solution {
public:
int minInsertions(string s) {
return s.length() - MaxNum(s);
}
int MaxNum(string s)
{
int c = s.length();
vector<vector> dp(c+1, vector©);
for (int j = 0; j < c; j++)
{
dp[1][j] = 1;
}
for (int len = 2; len <= c; len++)
{
for (int i = 0; i + len <= c; i++)
{
dp[len][i] = max(dp[len-1][i] ,dp[len-1][i+1]);
if (s[i] == s[i + len - 1])
{
dp[len][i] = max(dp[len][i], 2 + dp[len - 2][i + 1]);
}
}
}
return dp[c][0];
}
};

2023年2月 第二版

class Solution {
public:
int minInsertions(string s) {
string strInv(s.rbegin(), s.rend());
return s.length() - longestCommonSubsequence(s, strInv);
}
int longestCommonSubsequence(string text1, string text2) {
vector pre(text1.size()+1);
for (int i = 1; i <= text2.length(); i++)
{
vector dp(text1.size() + 1);
for (int j = 1; j <= text1.size();j++ )
{
dp[j] = max(pre[j], dp[j - 1]);
if (text2[i - 1] == text1[j - 1])
{
dp[j] = max(dp[j], pre[j - 1]+1);
}
}
pre.swap(dp);
}
return pre.back();
}
};

2023年7月版

class Solution {
public:
int minInsertions(string s) {
for (int i = 0; i <= s.length(); i++)
{
for (int j = 0; j <= s.length(); j++)
{
m_result[i][j] = -1;
}
}
return minInsertions(s, 0, s.length());
}
//左闭右开
int minInsertions(const string& s, int left, int r)
{
if (r - left <= 1)
{
return 0;
}
int& result = m_result[left][r];
if (-1 != result)
{
return result;
}
if (s[left] == s[r - 1])
{
return result =minInsertions(s, left + 1, r - 1);
}
return result = 1 + min(minInsertions(s, left + 1, r), minInsertions(s, left, r - 1));
}
int m_result[501][501];
};

扩展阅读

视频课程

有效学习:明确的目标 及时的反馈 拉伸区(难度合适),可以先学简单的课程,请移步CSDN学院,听白银讲师(也就是鄙人)的讲解。
https://edu.csdn.net/course/detail/38771

如何你想快

速形成战斗了,为老板分忧,请学习C#入职培训、C++入职培训等课程
https://edu.csdn.net/lecturer/6176

相关下载

想高屋建瓴的学习算法,请下载《喜缺全书算法册》doc版
https://download.csdn.net/download/he_zhidan/88348653

我想对大家说的话
闻缺陷则喜是一个美好的愿望,早发现问题,早修改问题,给老板节约钱。
子墨子言之:事无终始,无务多业。也就是我们常说的专业的人做专业的事。
如果程序是一条龙,那算法就是他的是睛

测试环境

操作系统:win7 开发环境: VS2019 C++17
或者 操作系统:win10 开发环境: VS2022 C++17
如无特殊说明,本算法用**C++**实现。

这篇关于【动态规划】【记忆化搜索】【回文】1312让字符串成为回文串的最少插入次数的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/673565

相关文章

MySQL常用字符串函数示例和场景介绍

《MySQL常用字符串函数示例和场景介绍》MySQL提供了丰富的字符串函数帮助我们高效地对字符串进行处理、转换和分析,本文我将全面且深入地介绍MySQL常用的字符串函数,并结合具体示例和场景,帮你熟练... 目录一、字符串函数概述1.1 字符串函数的作用1.2 字符串函数分类二、字符串长度与统计函数2.1

C# $字符串插值的使用

《C#$字符串插值的使用》本文介绍了C#中的字符串插值功能,详细介绍了使用$符号的实现方式,文中通过示例代码介绍的非常详细,需要的朋友们下面随着小编来一起学习学习吧... 目录$ 字符使用方式创建内插字符串包含不同的数据类型控制内插表达式的格式控制内插表达式的对齐方式内插表达式中使用转义序列内插表达式中使用

go动态限制并发数量的实现示例

《go动态限制并发数量的实现示例》本文主要介绍了Go并发控制方法,通过带缓冲通道和第三方库实现并发数量限制,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面... 目录带有缓冲大小的通道使用第三方库其他控制并发的方法因为go从语言层面支持并发,所以面试百分百会问到

详解MySQL中JSON数据类型用法及与传统JSON字符串对比

《详解MySQL中JSON数据类型用法及与传统JSON字符串对比》MySQL从5.7版本开始引入了JSON数据类型,专门用于存储JSON格式的数据,本文将为大家简单介绍一下MySQL中JSON数据类型... 目录前言基本用法jsON数据类型 vs 传统JSON字符串1. 存储方式2. 查询方式对比3. 索引

MySQL字符串常用函数详解

《MySQL字符串常用函数详解》本文给大家介绍MySQL字符串常用函数,本文结合实例代码给大家介绍的非常详细,对大家学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql字符串常用函数一、获取二、大小写转换三、拼接四、截取五、比较、反转、替换六、去空白、填充MySQL字符串常用函数一、

Python中反转字符串的常见方法小结

《Python中反转字符串的常见方法小结》在Python中,字符串对象没有内置的反转方法,然而,在实际开发中,我们经常会遇到需要反转字符串的场景,比如处理回文字符串、文本加密等,因此,掌握如何在Pyt... 目录python中反转字符串的方法技术背景实现步骤1. 使用切片2. 使用 reversed() 函

一文详解SpringBoot中控制器的动态注册与卸载

《一文详解SpringBoot中控制器的动态注册与卸载》在项目开发中,通过动态注册和卸载控制器功能,可以根据业务场景和项目需要实现功能的动态增加、删除,提高系统的灵活性和可扩展性,下面我们就来看看Sp... 目录项目结构1. 创建 Spring Boot 启动类2. 创建一个测试控制器3. 创建动态控制器注

MySQL查询JSON数组字段包含特定字符串的方法

《MySQL查询JSON数组字段包含特定字符串的方法》在MySQL数据库中,当某个字段存储的是JSON数组,需要查询数组中包含特定字符串的记录时传统的LIKE语句无法直接使用,下面小编就为大家介绍两种... 目录问题背景解决方案对比1. 精确匹配方案(推荐)2. 模糊匹配方案参数化查询示例使用场景建议性能优

MySQL 获取字符串长度及注意事项

《MySQL获取字符串长度及注意事项》本文通过实例代码给大家介绍MySQL获取字符串长度及注意事项,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录mysql 获取字符串长度详解 核心长度函数对比⚠️ 六大关键注意事项1. 字符编码决定字节长度2

springboot如何通过http动态操作xxl-job任务

《springboot如何通过http动态操作xxl-job任务》:本文主要介绍springboot如何通过http动态操作xxl-job任务的问题,具有很好的参考价值,希望对大家有所帮助,如有错... 目录springboot通过http动态操作xxl-job任务一、maven依赖二、配置文件三、xxl-