【动态规划篇】最少分割回文 编辑距离 不同的子序列

news2024/11/24 4:54:48

🌠作者:@阿亮joy.
🎆专栏:《数据结构与算法要啸着学》
🎇座右铭:每个优秀的人都有一段沉默的时光,那段时光是付出了很多努力却得不到结果的日子,我们把它叫做扎根
在这里插入图片描述


目录

    • 👉最少分割回文👈
    • 👉编辑距离👈
    • 👉不同的子序列👈
    • 👉总结👈

👉最少分割回文👈

给定一个字符串 s,请将 s 分割成一些子串,使每个子串都是回文串。返回符合要求的最少分割次数 。

在这里插入图片描述

思路:

在这里插入图片描述

class Solution 
{
private:
    bool isPalindrome(const string& s, int begin, int end)
    {
        while(begin < end)
        {
            if(s[begin] != s[end])
            {
                return false;
            }
            ++begin;
            --end;
        }
        return true;
    }

public:
    int minCut(string s) 
    {
        int len = s.size();
        vector<int> minCut(len + 1);
        // 初始状态:F(i) = i - 1
        for(int i = 1; i <= len; ++i)
        {
            minCut[i] = i - 1;
        }

        for(int i = 2; i <= len; ++i)
        {
            // [1, i]整体是回文串
            if(isPalindrome(s, 0, i - 1))
            {
                minCut[i] = 0;
                continue;
            }
            // j < i && [j + 1, i]是否为回文串
            for(int j = 1; j < i; ++j)
            {
                if(isPalindrome(s, j, i - 1))
                {
                    minCut[i] = min(minCut[i], minCut[j] + 1);
                }
            }
        }
        return minCut[len];
    }
};

在这里插入图片描述

class Solution 
{
private:
    bool isPalindrome(const string& s, int begin, int end)
    {
        while(begin < end)
        {
            if(s[begin] != s[end])
            {
                return false;
            }
            ++begin;
            --end;
        }
        return true;
    }

public:
    int minCut(string s) 
    {
        int len = s.size();
        vector<int> minCut(len + 1);
        // 初始状态:F(i) = i - 1
        for(int i = 0; i <= len; ++i)
        {
            minCut[i] = i - 1;
        }
        // F(0) = -1,若整个字符串为回文串,也能得出最小分割次数为0
        for(int i = 2; i <= len; ++i)
        {
            // j < i && [j + 1, i]是否为回文串
            for(int j = 0; j < i; ++j)
            {
                if(isPalindrome(s, j, i - 1))
                {
                    minCut[i] = min(minCut[i], minCut[j] + 1);
                }
            }
        }
        return minCut[len];
    }
};

在这里插入图片描述
上面的解法是 O(N ^ 3) 的算法,两层 for 循环再加一个判断回文串 O(N) 的算法,所以这个解法的时间复杂度为 O(N ^ 3)。我们可以先将回文串的结果保存下来,要用时可以直接用,这样就可以将时间复杂度将到 O(N ^ 2) 了。

判断回文串也是需要用到动态规划的。

在这里插入图片描述

class Solution 
{
private:
    vector<vector<bool>> getMat(const string& s)
    {
        int n = s.size();
        vector<vector<bool>> Mat(n, vector<bool>(n, false));

        // 从矩阵的右下角开始更新
        for(int i = n - 1; i >= 0; --i)
        {
            for(int j = i; j < n; ++j)
            {
                if(j == i)  // 初始状态
                    Mat[i][j] = true;
                else if(j == i + 1)
                    Mat[i][j] = s[i] == s[j];
                else    
                    Mat[i][j] = ((s[i] == s[j]) && (Mat[i + 1][j - 1]));
            }
        }

        return Mat;
    }

public:
    int minCut(string s) 
    {
        int len = s.size();
        vector<vector<bool>> Mat = getMat(s);
        vector<int> minCut(len + 1);
        // 初始状态:F(i) = i - 1
        for(int i = 0; i <= len; ++i)
        {
            minCut[i] = i - 1;
        }
        // F(0) = -1,若整个字符串为回文串,也能得出最小分割次数为0
        for(int i = 2; i <= len; ++i)
        {
            // j < i && [j + 1, i]是否为回文串
            for(int j = 0; j < i; ++j)
            {
                if(Mat[j][i - 1])
                {
                    minCut[i] = min(minCut[i], minCut[j] + 1);
                }
            }
        }
        return minCut[len];
    }
};

在这里插入图片描述
该解法的时间复杂度为 O(N ^ 2),空间复杂度为 O(N ^ 2),典型的以空间换时间的做法。

👉编辑距离👈

给你两个单词 word1 和 word2, 请返回将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

  • 插入一个字符
  • 删除一个字符
  • 替换一个字符

在这里插入图片描述

思路:

在这里插入图片描述

class Solution 
{
public:
    int minDistance(string word1, string word2) 
    {
        int row = word1.size();
        int col = word2.size();

        vector<vector<int>> minEdit(row + 1, vector<int>(col + 1));
        // 初始状态:F(i, 0) = 0 和 F(0, j) = j
        for(int i = 0; i <= row; ++i)   minEdit[i][0] = i;
        for(int j = 1; j <= col; ++j)   minEdit[0][j] = j;

        for(int i = 1; i <= row; ++i)
        {
            for(int j = 1; j <= col; ++j)
            {
                // 插入和删除
                minEdit[i][j] = min(minEdit[i][j - 1], minEdit[i - 1][j]) + 1;
                // 替换 word1[i - 1]是否等于word2[j - 1]
                if(word1[i - 1] == word2[j - 1])
                {
                    minEdit[i][j] = min(minEdit[i][j], minEdit[i - 1][j - 1]);
                }
                else
                {
                    minEdit[i][j] = min(minEdit[i][j], minEdit[i - 1][j - 1] + 1);
                }
            }
        }
        return minEdit[row][col];
    }
};

在这里插入图片描述

👉不同的子序列👈

给定一个字符串 s 和一个字符串 t ,计算在 s 的子序列中 t 出现的个数。

字符串的一个子序列是指,通过删除一些(也可以不删除)字符且不干扰剩余字符相对位置所组成的新字符串。(例如,“ACE” 是 “ABCDE” 的一个子序列,而 “AEC” 不是)

题目数据保证答案符合 32 位带符号整数范围。

在这里插入图片描述

思路:

在这里插入图片描述

class Solution 
{
public:
    int numDistinct(string s, string t) 
    {
        int row = s.size();
        int col = t.size();
        
        vector<vector<unsigned int>> dp(row + 1, vector<unsigned int>(col + 1, 0));
        for(int i = 0; i <= row; ++i)   dp[i][0] = 1;   // 初始状态
        for(int i = 1; i <= row; ++i)
        {
            for(int j = 1; j <= col; ++j)
            {
                if(s[i - 1] == t[j - 1])
                    dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
                else
                    dp[i][j] = dp[i - 1][j];
            }
        }
        return dp[row][col];
    }
};

在这里插入图片描述

空间复杂度优化

由于当前的dp[i][j]仅取决于dp[i - 1][j - 1]dp[i - 1][j],所以我们不需要用二维数组将所有状态的解都保留下来,可以用一维数组将上一次的解保留下来就行了。但需要注意的是,需要从后向前更新,不然无法拿到上一次的解。

class Solution 
{
public:
    int numDistinct(string s, string t) 
    {
        int row = s.size();
        int col = t.size();
        
        // 初始状态
        vector<unsigned int> dp(col + 1, 0);
        dp[0] = 1;
        for(int i = 1; i <= row; ++i)
        {
            for(int j = col; j >= 1; --j)
            {
                if(s[i - 1] == t[j - 1])
                    dp[j] = dp[j - 1] + dp[j];  // dp += dp[i - 1]
                
                // s[i - 1] != t[j - 1]时,不需要更新dp[j]
            }
        }
        return dp[col];
    }
};

在这里插入图片描述

👉总结👈

动态规划的难点:

  • 状态如何定义:从问题中抽象出状态,每一个状态都对应着一个子问题。状态的定义可能不止一种方式,那如何定义状态的合理性呢?某一个状态的阶或者多个状态的解能否推出最终问题的解,也就是状态之间能够形成递推关系(状态转移方程)。
  • 一维状态 VS 二维状态:首先尝试一维状态,如果一维状态的合理性不满足时,再去尝试二维状态。
  • 常见问题的状态:字符串:状态一般对应子串,状态一般每次增加一个新的字符。二维状态有时候能够优化成一维状态。

那么以上就是本篇博客的全部内容了,如果大家觉得有收获的话,可以点个三连支持一下!谢谢大家!💖💝❣️

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

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

相关文章

音视频技术开发周刊 | 277

每周一期&#xff0c;纵览音视频技术领域的干货。新闻投稿&#xff1a;contributelivevideostack.com。GNNear&#xff1a;基于近内存处理的大规模图神经网络训练加速器图神经网络(GNNs)已经成为分析非欧几里得图数据的最新算法。然而&#xff0c;实现高效的GNN训练是一项挑战&…

西门子1513CPU冗余组态

西门子1513R冗余配置 1、打开博图16软件&#xff0c;新建项目&#xff0c;添加新设备&#xff0c;在弹出的控制器目录下找到CPU 1513R-1 PN硬件&#xff0c;然后系统自动生成PLC_1和PLC_2&#xff1b; 2、打开设备组态中的网络视图&#xff0c;添加接口模块&#xff1b; 3、在…

Springboot 统计 代码执行耗时时间 ,玩法多到眼花

前言 近日群里有萌新提到关于统计代码执行时间的事&#xff1a; 开始 System.currentTimeMillis() 减去 结束 System.currentTimeMillis() 等于 耗时 其实我个人感觉OK的&#xff0c;就这样就蛮好的&#xff0c;很多项目都是这样用的。 简简单单的挺好。 这一篇就是 …

基于Java( jsp+servlet+javabean)+SQL sever 2017实现(Web)高校选课管理系统【100010058】

一、需求分析 开发意义&#xff1a; 随着信息技术不断向深入发展&#xff0c;越来越多的学校开始着手信息化建设。其中学生选课、成绩信息化管理就是其中重要的一块内容。学生选课与成绩信息规模大、项目条数多、信息量庞大&#xff0c;传统的人工管理方式显然已经无法满足要求…

买不到的数目(蓝桥杯C/C++A组真题详解)

题目详细&#xff1a; 题目思路&#xff1a; 对于这个题有一个定理 如果 a,b 均是正整数且互质&#xff0c;那么由 axby&#xff0c;x≥0&#xff0c;y≥0 不能凑出的最大数是 &#xff1a; a*b-a-b 具体的证明过程这里就不赘述 感兴趣的同学可以自行查找 这里就提供一种思…

rk3568 | rk平台GPIO冲突检测小技巧

上一篇我们讲解了如何编写gpio驱动&#xff0c;但是实际操作中&#xff0c;经常发现gpio引脚被占用的情况发生&#xff0c;那么本篇文章就详细讲解rxw平台下如何快速定位gpio复用问题以及如何解决。 一、GPIO寄存器查找 要想查看某个GPIO引脚可以配置的功能以及地址信息&…

Http协议基础

Http 是什么&#xff1f; Http 作为 WWW 的重要组成部分被提出 (World Wide Web) 而当时的 WWW 是为了帮助研究者更好的进行知识共享 基本理念&#xff1a;文档之间的相互关联形成超文本&#xff0c;最终连成相互参阅的 WWW Http (Hyper Text Transfer Protocol) 用于定义文…

QUIC的优势与缺陷

被寄予厚望的下一代互联网传输协议&#xff0c;QUIC究竟有哪些优点呢&#xff1f; 总结如下&#xff1a; 多路复用&#xff1a;QUIC升华了HTTP/2中的多路复用技术&#xff0c;实现了基于互相独立的多流&#xff08;多通道&#xff09;数据传输&#xff0c;从根本上解决了TCP存在…

基于C语言学生信息教务管理系统编程设计

一.实现功能 1.从键盘添加学生信息 2.从文件添加学生信息 3.显示学生信息到屏幕 4.显示学生信息到文件 5.删除学生信息 6.插入学生信息 7.查找学生信息 8.成绩排名 二、相关代码 #include<stdio.h> #include<stdlib.h> //使用malloc函数以及exit函数 #include<…

力扣(LeetCode)1759. 统计同构子字符串的数目(C++)

题目描述 双指针数学 根据同构字符串的定义&#xff0c;还有示例&#xff0c;发现同构子字符串的数量&#xff0c;只和字母相同的区间有关。如abbcccaa&#xff0c;有 444 个影响答案的区间&#xff0c;直观切分为a bb ccc aa&#xff0c;用空格划分区间。遍历的任务就是维护这…

灵动岛前端Ui

一、前言 灵动岛&#xff08;Dynamic Island &#xff09;是什么&#xff1f; 灵动岛&#xff0c;是苹果公司iPhone 14 Pro系列 [2] 交互UI&#xff0c;让虚拟软件和硬件的交互变得更为流畅。当有来电、短信等通知时&#xff0c;灵动岛会变化它的形态&#xff0c;以便让用户能…

【大数据】M1 mac win docker安装kafka+mysql+canal

文章目录kafkadocker-compose创建kafka容器启动以后&#xff0c;访问容器&#xff0c;并且发送消息测试问题Exception in thread "main" kafka.zookeeper.ZooKeeperClientTimeoutException: Timed out waiting for connection while in state: CONNECTINGmysqldocker…

LAPS本地管理员密码之使用PowerShell查看和重置密码

目录 一、PowerShell策略设置 二、引入AdmPwd.PS模块 三、查看密码 四、强制重置密码 文章主要介绍在部署了LAPS后&#xff0c;怎么使用PowerShell查看和管理域内本地管理员密码。需要注意的是被操作的电脑需要加域&#xff0c;所有操作都在域内环境下进行。 LAPS介绍 LAP…

Spring Boot 知识总结

Spring Boot 知识总结 一、Spring Boot基础 1.1 什么是Spring Spring是一个开源框架&#xff0c;2003年兴起的一个Java轻量级开发框架&#xff0c;作者&#xff1a;Rod Johnson。 Spring是为了解决企业级应用开发的复杂性而创建的&#xff0c;简化开发。 Spring是如何简化…

LeetCode 每日一题——1759. 统计同构子字符串的数目

1.题目描述 1759. 统计同构子字符串的数目 难度中等43 给你一个字符串 s &#xff0c;返回 s 中 同构子字符串 的数目。由于答案可能很大&#xff0c;只需返回对 109 7 取余 后的结果。 同构字符串 的定义为&#xff1a;如果一个字符串中的所有字符都相同&#xff0c;那么…

Rancher RFO 正式 GA

Rancher RFO GA RFO 是 Rancher For openEuler 的缩写&#xff0c;旨在面向 openEuler 打造 Rancher 基础平台。其中最核心的工作是打造一款面向 openEuler 生态的 Kubernetes 发行版。它基于上游 RKE2 的技术栈&#xff0c;构建物采用 openEuler base image&#xff0c;致力于…

C语言及算法设计课程实验一:C程序的运行环境和运行C程序的方法

C语言及算法设计课程实验一&#xff1a;C程序的运行环境和运行C程序的方法一、实验目的二、实验内容2.1、输人并运行一个简单的正确的程序2.2、输人并编辑一个有错误的C程序2.3、输入并运行一个需要在运行时输入数据的程序2.4、运行一个自己编写的程序三、实验步骤3.1、输人并运…

Android OpenGL ES 学习(十一) –渲染YUV视频以及视频抖音特效

OpenGL 学习教程 Android OpenGL ES 学习(一) – 基本概念 Android OpenGL ES 学习(二) – 图形渲染管线和GLSL Android OpenGL ES 学习(三) – 绘制平面图形 Android OpenGL ES 学习(四) – 正交投影 Android OpenGL ES 学习(五) – 渐变色 Android OpenGL ES 学习(六) – 使用…

基于MWORKS.Sysplorer的电子控制器应用案例——永磁同步电机FOC算法建模

1 前言 MWORKS是面向数字工程的新一代科学计算与系统建模仿真平台&#xff0c;可提供机械、电子、液压、控制、热、信息等多领域统一建模仿真环境。经过同元持续攻关&#xff0c;全新推出的MWORKS.Sysplorer嵌入式代码生成器&#xff0c;现已支持面向电子控制器的产品级的嵌入…

循环神经网络的简洁实现

参考8.6. 循环神经网络的简洁实现 — 动手学深度学习 2.0.0 documentation 本节将展示如何使用深度学习框架的高级API提供的函数更有效地实现相同的语言模型。 我们仍然从读取时光机器数据集开始。 pip install mxnet1.7.0.post1 pip install d2l0.15.0 from mxnet import n…