【LeetCode】动态规划—1312. 让字符串成为回文串的最少插入次数(附完整Python/C++代码)

news2024/11/24 20:59:35

动态规划—1312. 让字符串成为回文串的最少插入次数

  • 题目描述
  • 前言
  • 基本思路
    • 1. 问题定义
      • 目标:
      • 举例:
    • 2. 理解问题和递推关系
      • 动态规划思路:
    • 3. 解决方法
      • 动态规划方法
      • 伪代码:
    • 4. 进一步优化
    • 5. 小总结
  • Python代码
      • Python代码解释:
  • C++代码
      • C++代码解释:
  • 总结

题目描述

在这里插入图片描述

前言

最少插入次数使字符串变为回文 是一个经典的动态规划问题。我们需要计算出通过最少的插入次数将给定的字符串转换为回文字符串。回文字符串是指正读和反读相同的字符串。通过动态规划的思想,我们可以高效地解决这一问题,分析每个字符与其对称位置之间的关系。


基本思路

1. 问题定义

给定一个字符串 s,要求找到最少的插入步骤,使得这个字符串变为回文。

目标:

  • 找到可以将字符串 s 转换为回文所需的最小插入次数。

举例:

  • 输入:"mbadm"
  • 输出:2,因为通过插入字符可以将其变为 "mbdadbm""madbam"

2. 理解问题和递推关系

如果我们要求插入最少次数,使得一个字符串变为回文,可以反过来思考:我们可以找到该字符串的 最长回文子序列,然后剩下的字符可以通过插入来补齐,从而形成一个回文。

动态规划思路:

  1. 定义状态
    定义一个二维数组 dp[i][j],表示在区间 s[i...j] 内,将该子串变为回文所需的最少插入次数。

  2. 状态转移方程

    • s[i] == s[j] 时,不需要插入,dp[i][j] = dp[i+1][j-1]
    • s[i] != s[j] 时,我们可以选择插入字符使它们相等,因此有两种情况:
      1. s[i] 前插入 s[j],则状态转移为 dp[i][j] = dp[i][j-1] + 1
      2. s[j] 后插入 s[i],则状态转移为 dp[i][j] = dp[i+1][j] + 1
    • 最终取两者的最小值:
      d p [ i ] [ j ] = min ⁡ ( d p [ i + 1 ] [ j ] , d p [ i ] [ j − 1 ] ) + 1 dp[i][j] = \min(dp[i+1][j], dp[i][j-1]) + 1 dp[i][j]=min(dp[i+1][j],dp[i][j1])+1
  3. 边界条件

    • i == j,即字符串长度为1时,已经是回文,不需要插入,因此 dp[i][i] = 0
    • i > j,这种情况不可能存在,值为 0

3. 解决方法

动态规划方法

  1. 初始化二维数组 dpdp[i][j] 记录了从 ij 的子串所需的最少插入次数。
  2. 使用 状态转移方程 填充 dp 数组。
  3. 最终结果保存在 dp[0][n-1] 中,n 是字符串的长度。

伪代码:

initialize dp array with size n x n
for length from 2 to n:
    for i from 0 to n-length:
        j = i + length - 1
        if s[i] == s[j]:
            dp[i][j] = dp[i+1][j-1]
        else:
            dp[i][j] = min(dp[i+1][j], dp[i][j-1]) + 1
return dp[0][n-1]

4. 进一步优化

  • 空间优化:可以使用一维数组优化空间复杂度,只记录相邻状态的值。

5. 小总结

  • 问题转化:该问题可以通过寻找 最长回文子序列 的反向思路求解。
  • 时间复杂度:该解法的时间复杂度为 O(n^2),空间复杂度为 O(n^2)

以上就是让字符串成为回文串的最少插入次数问题的基本思路。


Python代码

class Solution:
    def minInsertions(self, s: str) -> int:
        n = len(s)
        # 初始化dp数组,dp[i][j] 表示将s[i:j+1]变为回文所需的最少插入次数
        dp = [[0] * n for _ in range(n)]
        
        # 从长度为2开始遍历子串
        for length in range(2, n + 1):
            for i in range(n - length + 1):
                j = i + length - 1
                if s[i] == s[j]:
                    dp[i][j] = dp[i + 1][j - 1]
                else:
                    dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1
        
        # 返回将整个字符串变为回文的最少插入次数
        return dp[0][n - 1]

Python代码解释:

  1. 初始化:创建二维 dp 数组,dp[i][j] 表示将 s[i:j+1] 变为回文的最少插入次数。
  2. 状态转移:通过比较 s[i]s[j],根据状态转移方程更新 dp 数组。
  3. 返回结果dp[0][n-1] 即为整个字符串变为回文的最少插入次数。

C++代码

class Solution {
public:
    int minInsertions(string s) {
        int n = s.size();
        // 初始化dp数组,dp[i][j] 表示将s[i:j+1]变为回文所需的最少插入次数
        vector<vector<int>> dp(n, vector<int>(n, 0));
        
        // 从长度为2开始遍历子串
        for (int length = 2; length <= n; ++length) {
            for (int i = 0; i <= n - length; ++i) {
                int j = i + length - 1;
                if (s[i] == s[j]) {
                    dp[i][j] = dp[i + 1][j - 1];
                } else {
                    dp[i][j] = min(dp[i + 1][j], dp[i][j - 1]) + 1;
                }
            }
        }
        
        // 返回将整个字符串变为回文的最少插入次数
        return dp[0][n - 1];
    }
};

C++代码解释:

  1. 初始化:创建二维数组 dpdp[i][j] 表示将 s[i:j+1] 变为回文的最少插入次数。
  2. 状态转移:通过动态规划递推公式更新 dp 数组。
  3. 返回结果dp[0][n-1] 即为将整个字符串变为回文的最少插入次数。

总结

  • 核心思想:通过动态规划求解最少插入次数来将字符串转换为回文。该问题可以转化为找出 最长回文子序列,然后剩余的字符通过插入进行补齐。
  • 时间复杂度:该方法的时间复杂度为 O(n^2),适合处理中等规模的字符串问题。
  • 应用场景:该问题展示了如何通过动态规划优化复杂问题的思路,同时也能帮助我们理解如何在字符串操作中利用递归关系处理类似的转换问题。

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

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

相关文章

基于Spring Boot的医疗病历B2B平台开发策略

第4章 系统设计 4.1 系统总体设计 系统不仅要求功能完善&#xff0c;而且还要界面友好&#xff0c;因此&#xff0c;对于一个成功的系统设计&#xff0c;功能模块的设计是关键。由于本系统可执行的是一般性质的学习信息管理工作&#xff0c;本系统具有一般适用性&#xff0c;其…

Java项目:148 基于springboot的校友管理系统

作者主页&#xff1a;舒克日记 简介&#xff1a;Java领域优质创作者、Java项目、学习资料、技术互助 文中获取源码 校友管理系统项目说明 ​ 本系统是一个学校与毕业生的交流平台。方便校友们了解母校的最新动态&#xff0c;同学的情况&#xff1b;同时学校也可以通过平台了解…

<<迷雾>> 第11章 全自动加法计算机(2)--5 比特存储器 示例电路

可以读/写单个5位二进制数的存储器. info::操作说明 将多个比特单元组合的结果, 整体操作流程类似, 只是可同时读取多位 注: D0~D4 处没有引入写入测试开关, 读者可仿照前面自行引入 primary::在线交互操作链接 https://cc.xiaogd.net/?startCircuitLinkhttps://book.xiaogd.n…

【React】React18核心源码解读

前言 本文使用 React18.2.0 的源码&#xff0c;如果想回退到某一版本执行git checkout tags/v18.2.0即可。如果打开源码发现js文件报ts类型错误请看本人另一篇文章&#xff1a;VsCode查看React源码全是类型报错如何解决。 阅读源码的过程&#xff1a; 下载源码 观察 package…

MySQL 【日期】函数大全(二)

DATE_ADDDATE_FORMATDATE_SUBDATEDIFFDAYDAYNAMEDAYOFMONTHDAYOFWEEK 1、DATE_ADD DATE_ADD(date, value) &#xff1a;在指定的日期/时间上加上指定的时间间隔加并返回新的日期/时间。 DATE_ADD(date, value) DATE_ADD(date, INTERVAL value unit) date&#xff1a;需要操作…

Qt-系统处理键盘按键相关事件(58)

目录 描述 使用 单个按键 组合键 描述 Qt 中的按键事件是通过 QKeyEvent 类来实现的。当键盘上的按键被按下或者被释放时&#xff0c;键盘事件便会触发 Qt 中对按键事件进行了封装&#xff0c;QShortCut 就是封装出来的&#xff0c;这里我们介绍底层的函数 使用 单个按键…

如何将csdn文章导出为pdf

前言 在csdn上浏览文章的时候我发现有的文章支持pdf导出&#xff0c;但是有的文章不支持pdf导出&#xff0c;为了解决能将csdn上所有文章都能以pdf格式导出遂作此文。 正文 先上代码&#xff1a; (function(){use strict;var contentBox $("div.article_content")…

智能 AI 应用为什么需要知识库

智能 AI 应用为什么需要知识库 上回我们讲到如何在 Dify 上搭建企业知识库&#xff0c;并引入大语言模型应用中&#xff0c;实现企业内部知识助手。 使用 Dify 快速搭建企业内部知识助手。 其中提到的企业知识库&#xff0c;正是 “检索增强生成(Retrieval-Augmented Generat…

开放式耳机哪个品牌音质好?开放式耳机排行榜10强推荐!

耳机在我们的日常生活中扮演着重要角色&#xff0c;无论是上班路上还是运动时&#xff0c;它们都能帮助我们放松并增强安全感。选择一款合适的耳机很关键&#xff0c;开放式耳机因其设计&#xff0c;在不同场合都适用&#xff0c;特别是在运动时&#xff0c;它们提供了稳固而舒…

【笔记】Day2.2.1表设计说明

主键ID一般使用bigint类型 运送类型 使用比int更小的tinyint类型 eg&#xff1a;普快代表1 特快代表2&#xff08;没写反&#xff09; 关联城市 varchar 2代表京津冀 3代表江浙沪 4代表川渝 首重和续重都有小数点 故使用double 轻抛系数都为整数 故使用int 创建时间和修改…

基于SpringBoot+Vue的体育馆场地预约系统

作者&#xff1a;计算机学姐 开发技术&#xff1a;SpringBoot、SSM、Vue、MySQL、JSP、ElementUI、Python、小程序等&#xff0c;“文末源码”。 专栏推荐&#xff1a;前后端分离项目源码、SpringBoot项目源码、Vue项目源码、SSM项目源码、微信小程序源码 精品专栏&#xff1a;…

【测试】自动化——概念篇

自动化测试 自动化概念 什么是自动化&#xff1f; 自动化操作在生活中处处可见&#xff0c;自动化洒水机、自动洗手液、超市自动闸门。 自动化测试——>自动的测试软件&#xff08;减少人力和时间的消耗&#xff0c;提高软件的测试质量&#xff09;。 人力&#xff1a;2…

自定义实现项目进度图

目录 0.背景 1. 演示效果 2.实现原理 2.1 处理表头数据&#xff08;日期对应的是星期几&#xff09; 2.2 获取项目数据 2.3 合并单元格 3.源码 0.背景 目遇到一个展示项目进度的需求&#xff0c;类似甘特图的效果&#xff0c;不同的是&#xff0c;每一个项目都有计划和实…

MySQL:基于Spring监听Binlog日志

binlog的三种模式 MySQL 的二进制日志&#xff08;binlog&#xff09;有三种不同的格式&#xff0c;通常被称为 binlog 模式。这三种模式分别是 Statement 模式、Row 模式和Mixed 模式。 Statement 模式&#xff1a; 在 Statement 模式下&#xff0c;MySQL 记录每个会更改数…

代码随想录训练营Day30 | 491.递增子序列 | 46.全排列 | 47.全排列 II

学习文档&#xff1a;代码随想录 (programmercarl.com) 学习视频&#xff1a;代码随想录算法公开课 | 最强算法公开课 | 代码随想录 (programmercarl.com) Leetcode 491. 非递减子序列 题目描述 给你一个整数数组 nums &#xff0c;找出并返回所有该数组中不同的递增子序列…

AI赋能!0基础小白自媒体创业,成功率提升90%的秘诀?

本文背景 好多小伙伴也想写公众号文章&#xff0c;但是自己又没有写过&#xff0c;不知道如何开始。 今天分享个小方法&#xff0c;就算是写作新手&#xff0c;也能靠 AI 快速上手&#xff0c;写出好内容&#xff01; 一起来看看怎么用 AI 工具 助力写作&#xff0c;提高效率&a…

STM32(十八):实时时钟

时间戳 Unix 时间戳&#xff08;Unix Timestamp&#xff09;定义为从UTC/GMT的1970年1月1日0时0分0秒开始所经过的秒数&#xff0c;不考虑闰秒。 时间戳存储在一个秒计数器中&#xff0c;秒计数器为32位/64位的整型变量。 世界上所有时区的秒计数器相同&#xff0c;不同时…

一次性使用病毒采样管-保存运输呼吸道 肠道等多种病毒样本的有力工具!

远离了新冠病毒却又来了流感病毒、手足口、猴痘病毒、诺如病毒等多种病毒&#xff0c;对于众多病毒的检测诊断&#xff0c;确保病毒样本的高效采集、安全保存和准确运输是至关重要的。为了满足这一需求&#xff0c;一次性使用病毒采样管应运而生。 在研究、医学诊断和疫情监测…

10.12 标准IO

练习&#xff1a;针对fscanf和fprintf练习 有如下结构体&#xff1a; typedef struct Student { char name[20]; int id; float chinese;//语文成绩 float math; float english; float physical; float chemical; float biological; }stu_t; *Pstu_t//声明学生结构体类型 在栈区…

逆向思维的力量:Prolog在游戏编程中的应用与代码实践

在主流游戏开发语言如C++、Python和Unity统治的今天,Prolog作为一种基于逻辑编程的语言,似乎与游戏开发不太沾边。然而,Prolog的逻辑推理机制和简洁的语法在解决复杂逻辑问题上有着独特的优势,尤其是在人工智能(AI)决策和路径规划等领域。通过Prolog,我们可以以极简的代…