算法学习——LeetCode力扣动态规划篇10(583. 两个字符串的删除操作、72. 编辑距离、647. 回文子串、516. 最长回文子序列)

算法学习——LeetCode力扣动态规划篇10

在这里插入图片描述

583. 两个字符串的删除操作

583. 两个字符串的删除操作 - 力扣(LeetCode)

描述

给定两个单词 word1 和 word2 ,返回使得 word1 和 word2 相同所需的最小步数。

每步 可以删除任意一个字符串中的一个字符。

示例

示例 1:

输入: word1 = “sea”, word2 = “eat”
输出: 2
解释: 第一步将 “sea” 变为 “ea” ,第二步将 "eat "变为 “ea”

示例 2:

输入:word1 = “leetcode”, word2 = “etco”
输出:4

提示

1 <= word1.length, word2.length <= 500
word1 和 word2 只包含小写英文字母

代码解析

动态规划

和1143相同,只要求出两个字符串的最长公共子序列长度即可,那么除了最长公共子序列之外的字符都是必须删除的,最后用两个字符串的总长度减去两个最长公共子序列的长度就是删除的最少步数。

class Solution {
public:
    
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1 , vector<int>(word2.size()+1 ,0));

        for(int i=0 ;i<word1.size() ;i++)
        {
            for(int j=0 ;j<word2.size() ;j++)
            {
                if(word1[i] == word2[j]) dp[i+1][j+1] = dp[i][j] + 1;
                else dp[i+1][j+1] = max(dp[i][j+1],dp[i+1][j]);
            }
        }
        return word1.size() + word2.size() - 2*dp[word1.size()][word2.size()];
    }
};

72. 编辑距离

72. 编辑距离 - 力扣(LeetCode)

描述

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

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

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

示例

示例 1:

输入:word1 = “horse”, word2 = “ros”
输出:3
解释:
horse -> rorse (将 ‘h’ 替换为 ‘r’)
rorse -> rose (删除 ‘r’)
rose -> ros (删除 ‘e’)

示例 2:

输入:word1 = “intention”, word2 = “execution”
输出:5
解释:
intention -> inention (删除 ‘t’)
inention -> enention (将 ‘i’ 替换为 ‘e’)
enention -> exention (将 ‘n’ 替换为 ‘x’)
exention -> exection (将 ‘n’ 替换为 ‘c’)
exection -> execution (插入 ‘u’)

提示

0 <= word1.length, word2.length <= 500
word1 和 word2 由小写英文字母组成

代码解析

动态规划
  • 确定dp数组以及下标的含义
    dp[i][j] 表示前 i 个字符的word1,和前 j 个字符的word2,最近编辑距离。
  • 递推公式
    • if (word1[ i ] == word2[ j ]) 那么说明不用任何编辑,
      即dp[i+1][j+1] = dp[i ][j ];
    • if (word1[ i ] != word2[ j ]) 有三种情况
      • 删除world1
        word1第 i 个字符删除一个元素,就是world1第 i -1 与world2第 j 再加上一个操作。
        即 dp[i+1][j+1] = dp[ i ][ j+1] + 1;
      • 删除world2(相当于添加world1)
        word2第 j 个字符删除一个元素,就是world1第 i 与world2第 j -1 再加上一个操作。
        即 dp[i+1][j+1] = dp[ i +1][ j] + 1;
      • 替换元素
        word1第 i 个字符和word1第 i -1个字符替换,world2同样,就是world1第 i -1 与world2第 j -1 再加上一个操作。
        即 dp[i+1][j+1] = dp[ i ][ j] + 1;
      • 最终三种情况取最小
        dp[i+1][j+1] = min( dp[i][j] , min(dp[i][j+1],dp[i+1][j])) + 1;
  • dp数组初始化
    • dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。
      那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;

    • 同理dp[0][j] = j;
      在这里插入图片描述
      在这里插入图片描述

class Solution {
public:
    int minDistance(string word1, string word2) {
        vector<vector<int>> dp(word1.size()+1 , vector<int>(word2.size()+1));

        for(int i=0 ; i<word1.size();i++)
            dp[i+1][0] = i+1;
        for(int j=0 ; j<word2.size();j++)
            dp[0][j+1] = j+1;
        
        for(int i=0;i<word1.size();i++)
        {
            for(int j=0; j<word2.size();j++)
            {
                if(word1[i] == word2[j]) dp[i+1][j+1] = dp[i][j];
                else dp[i+1][j+1] = min( dp[i][j] , min(dp[i][j+1],dp[i+1][j])) + 1;
            }
        }
        return dp[word1.size()][word2.size()];
    }
};

647. 回文子串

647. 回文子串 - 力扣(LeetCode)

描述

给你一个字符串 s ,请你统计并返回这个字符串中 回文子串 的数目。

回文字符串 是正着读和倒过来读一样的字符串。

子字符串 是字符串中的由连续字符组成的一个序列。

具有不同开始位置或结束位置的子串,即使是由相同的字符组成,也会被视作不同的子串。

示例

示例 1:

输入:s = “abc”
输出:3
解释:三个回文子串: “a”, “b”, “c”

示例 2:

输入:s = “aaa”
输出:6
解释:6个回文子串: “a”, “a”, “a”, “aa”, “aa”, “aaa”

提示

1 <= s.length <= 1000
s 由小写英文字母组成

代码解析

暴力法
class Solution {
public:
    bool cheak(const string s , int left,int right)
    {
        for(int i=left ,j=right; i<=(right-left)/2 +left; i++,j--)
        {
            if(s[i]!=s[j]) return false;
        }
        return true;
    }
    int countSubstrings(string s) {
        if(s.size()<=1) return 1;
        int num=0;
        int left=0,right=1;
        for(int left=0 ; left<s.size() ;left++)
        {
            for(right=left ; right<s.size();right++)
            {
                if(cheak(s,left,right)==1)
                {
                    num++;
                    // cout<<left<<' '<<right<<endl;
                }
            }
        }
        return num;
    }
};

动态规划
  • 确定dp数组(dp table)以及下标的含义
    布尔类型的dp[i][j]:表示区间范围[i,j] (注意是左闭右闭)的子串是否是回文子串,如果是dp[i][j]为true,否则为false。

  • 确定递推公式
    在确定递推公式时,就要分析如下几种情况。

    • 当s[i]与s[j]不相等,那没啥好说的了,dp[i][j]一定是false。

    • 当s[i]与s[j]相等时,这就复杂一些了,有如下三种情况
      情况一:下标i 与 j相同,同一个字符例如a,当然是回文子串
      情况二:下标i 与 j相差为1,例如aa,也是回文子串
      情况三:下标:i 与 j相差大于1的时候,例如cabac,此时s[i]与s[j]已经相同了,我们看i到j区间是不是回文子串就看aba是不是回文就可以了,那么aba的区间就是 i+1 与 j-1区间,这个区间是不是回文就看dp[i + 1][j - 1]是否为true。

  • dp数组如何初始化
    dp[i][j]可以初始化为true么? 当然不行,怎能刚开始就全都匹配上了。
    所以dp[i][j]初始化为false。

  • 确定遍历顺序
    遍历顺序可有有点讲究了。
    首先从递推公式中可以看出,情况三是根据dp[i + 1][j - 1]是否为true,在对dp[i][j]进行赋值true的。
    dp[i + 1][j - 1] 在 dp[i][j]的左下角,
    一定要从下到上,从左到右遍历,这样保证dp[i + 1][j - 1]都是经过计算的。
    因为dp[i][j]的定义,所以j一定是大于等于i的,那么在填充dp[i][j]的时候一定是只填充右上半部分。
    在这里插入图片描述

class Solution {
public:
    int countSubstrings(string s) {
        if(s.size()<=1) return 1;
        vector<vector<bool>> dp(s.size(),vector<bool>(s.size() , false));
        int num = 0;
        for(int i=s.size()-1 ; i>=0;i--)
            for(int j=i ;j<s.size();j++)
            	//s[i]==s[j]为首尾相同
            	//并且j-i <= 1为"a"或者"aa"的情况,为回文串
            	//如果j-i不是<=1,但是dp[i+1][j-1]==true,也是回文串,因为首位相同中间是回文串
            	//如dabcd,首位d相同,中间dp[i+1][j-1]为abc也是回文串,即dabcd为回文串
                if(  s[i]==s[j] &&
                    (j-i <= 1||dp[i+1][j-1]==true)  )  
                {
                    num++;
                    dp[i][j] = true;
                }
        return num;
    }
};

516. 最长回文子序列

516. 最长回文子序列 - 力扣(LeetCode)

描述

给你一个字符串 s ,找出其中最长的回文子序列,并返回该序列的长度。

子序列定义为:不改变剩余字符顺序的情况下,删除某些字符或者不删除任何字符形成的一个序列。

示例

示例 1:

输入:s = “bbbab”
输出:4
解释:一个可能的最长回文子序列为 “bbbb” 。

示例 2:

输入:s = “cbbd”
输出:2
解释:一个可能的最长回文子序列为 “bb” 。

提示

1 <= s.length <= 1000
s 仅由小写英文字母组成

代码解析

动态规划
  • 确定dp数组(dp table)以及下标的含义
    dp[i][j]:字符串s在[i, j]范围内最长的回文子序列的长度为dp[i][j]。

  • 确定递推公式
    在判断回文子串的题目中,关键逻辑就是看s[i]与s[j]是否相同。

    • 如果s[i]与s[j]相同,
      • j - i ==0 , dp[i][j] = 1;
      • j - i == 1, dp[i][j] = 2;
      • j - i > 2, dp[i][j] = dp[i + 1][j - 1] + 2;
        在这里插入图片描述
    • 如果s[i]与s[j]不同
      dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]);

在这里插入图片描述

  • 确定遍历顺序
    从递推公式dp[i][j] = dp[i + 1][j - 1] + 2 和 dp[i][j] = max(dp[i + 1][j], dp[i][j - 1]) 可以看出,dp[i][j]是依赖于dp[i + 1][j - 1] 和 dp[i + 1][j],
    也就是从矩阵的角度来说,dp[i][j] 下一行的数据。 所以遍历i的时候一定要从下到上遍历,这样才能保证,下一行的数据是经过计算的。
    在这里插入图片描述
class Solution {
public:
    int longestPalindromeSubseq(string s) {
        if(s.size()<=1) return s.size();
        vector<vector<int>> dp(s.size() , vector<int>(s.size() ,0));
        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])
                {
                    if(j==i) dp[i][j] = 1;
                    else if(j-i==1) dp[i][j] = 2;
                    else dp[i][j] = dp[i+1][j-1] + 2;

                    if(dp[i][j] > result) result = dp[i][j];
                }else
                {
                    dp[i][j] = max(dp[i][j-1],dp[i+1][j]);
                }
            }
                
        // for(int i=0;i<s.size();i++)
        // {
        //     for(int j=0;j<s.size();j++)
        //     cout<<dp[i][j]<<' ';
        
        //     cout<<endl;
        // }
        return result;
    }
};

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

Last-Modified:HTTP缓存控制机制解析

&#x1f90d; 前端开发工程师、技术日更博主、已过CET6 &#x1f368; 阿珊和她的猫_CSDN博客专家、23年度博客之星前端领域TOP1 &#x1f560; 牛客高级专题作者、打造专栏《前端面试必备》 、《2024面试高频手撕题》 &#x1f35a; 蓝桥云课签约作者、上架课程《Vue.js 和 E…

nodejs下载安装以及npm、yarn安装及配置教程

1、nodejs下载安装 ​ 1.1、使用nodejs版本管理工具下载安装&#xff0c;可一键安装、切换不同nodejs版本&#xff0c; nvm-setup.zip&#xff1a;安装版&#xff0c;推荐使用 本次演示的是安装版。 1、双击安装文件 nvm-setup.exe 选择nvm安装路径 例如&#xff1a;E:\Soft…

蓝桥杯算法题-图形排版

题目描述 小明需要在一篇文档中加入 N 张图片&#xff0c;其中第 i 张图片的宽度是 Wi&#xff0c;高度是 Hi。   假设纸张的宽度是 M&#xff0c;小明使用的文档编辑工具会用以下方式对图片进行自动排版&#xff1a; 1. 该工具会按照图片顺序&#xff0c;在宽度 M 以内&…

Mysql数据库:MHA高可用架构

目录 前言 一、MHA概述 1、什么是MHA 2、MHA的特点 3、MHA的组成 4、MHA的工作原理 5、故障切换备选主库的算法 二、部署MHA高可用架构 1、环境部署 2、部署主从同步 2.1 修改主配置文件并创建软链接 2.1.1 master 修改主配置文件并创建软连接 2.1.2 slave1 修改主…

【JavaSE】类和对象详解(下)

前言 面向对象程序的三大特性&#xff1a;封装、继承、多态~ 书接上回 类和对象&#xff08;上&#xff09;~ 欢迎关注个人主页&#xff1a;逸狼 创造不易&#xff0c;可以点点赞吗~ 如有错误&#xff0c;欢迎指出~ 目录 前言 封装 private public 快速生成可访问封装的方法 包…

ubuntu16.04 不支持 gcc-11,g++11

总结 ubuntu16.04 不支持 gcc-11&#xff0c;需要升级 18.04 或更高的版本。 背景 最近需要在我的 ubuntu16.04 电脑上安装 gcc-11&#xff0c;g-11&#xff0c;使用更高的版本来编译代码。根据网上查到的方式是添加以下的源并进行安装 sudo add-apt-repository ppa:ubuntu…

数据库之MyBatisPlus详解

MyBatisPlus MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window) 的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 官网地址&#xff1a;https://baomidou.com/ 一、入门案…

微信公众号迁移公证书在哪?

公众号迁移有什么作用&#xff1f;只能变更主体吗&#xff1f;很多小伙伴想做公众号迁移&#xff0c;但是不知道公众号迁移有什么作用&#xff0c;今天跟大家具体讲解一下。首先公众号迁移最主要的就是修改公众号的主体了&#xff0c;比如我们公众号原来是A公司的&#xff0c;现…

Ruoyi-Cloud-Plus_使用Docker部署分布式微服务系统_环境准备_001---SpringCloud工作笔记200

1.首先安装docker: 如果以前安装过首先执行: yum remove docker docker-client docker-client-latest docker-common docker-latest docker-latest-logrotate docker-logrotate docker-selinux docker-engine-selinux docker-engine 去卸载docker 2.安装dokcer需要的工具包…

linux下minio部署和nginx配置

1 下载minio wget https://dl.min.io/server/minio/release/linux-amd64/minio chmod x minio #启动minio&#xff0c;文件数据存放在/data目录 ./minio server /data2 部署minio 下载minio后赋予可执行权限就可以运行了&#xff0c;这里我整理了遇到的坑和解决问题的最终配置…

大模型面试准备(九):简单透彻理解MoE

节前&#xff0c;我们组织了一场算法岗技术&面试讨论会&#xff0c;邀请了一些互联网大厂朋友、参加社招和校招面试的同学&#xff0c;针对大模型技术趋势、大模型落地项目经验分享、新手如何入门算法岗、该如何备战、面试常考点分享等热门话题进行了深入的讨论。 合集在这…

【洛谷】P9241 [蓝桥杯 2023 省 B] 飞机降落

挺有意思的一道题&#xff0c;分享给大家 题目链接 P9241 [蓝桥杯 2023 省 B] 飞机降落 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn) 题目描述 输入格式 输出格式 输入输出样例 说明/提示 思路 一开始尝试贪心能不能做&#xff0c;但是不好确定飞机的顺序 因为这题的数…

第5篇:挖矿病毒(一)

0x00 前言 ​ 随着虚拟货币的疯狂炒作&#xff0c;挖矿病毒已经成为不法分子利用最为频繁的攻击方式之一。病毒传播者可以利用个人电脑或服务器进行挖矿&#xff0c;具体现象为电脑CPU占用率高&#xff0c;C盘可使用空间骤降&#xff0c;电脑温度升高&#xff0c;风扇噪声增大…

金融衍生品市场

金融衍生品市场 衍生金融品的作用衍生金融工具远期合约期货合约期权 衍生金融品的作用 套期保值&#xff08;Hedging&#xff09; 组合多头头寸(long position)与空头头寸(short position)例&#xff1a;股票与股指期货 投机 衍生金融工具 远期合约 定义&#xff1a;在将来…

C语言数组详解

一维数组 创建和初始化 数组就是一组相同元素的集合。 他的创建&#xff1a; char arr[10]; int arr1[5]; 数组创建中 [] 里不能是变量&#xff0c;但是在c99标准之后就可以了被称为变长数组&#xff0c;但是不常用&#xff0c;而且变长数组不能初始化。 初始化&#xff…

这两个比较经典的LVS问题怎么解?

今日景芯SoC VIP学员遇到的LVS问题&#xff0c;比较经典&#xff0c;大家先思考下。然后本文末尾分享下2.5GHz A72训练营的LVS解法&#xff1a; 问题1&#xff1a; 问题2&#xff1a; 修改后&#xff1a; 具体修改方案参见知识星球&#xff0c;接下来分享下2.5GHz A72项目的LV…

如何使用固定公网地址远程访问内网Axure RP生成的网站原型web页面

文章目录 前言1.在AxureRP中生成HTML文件2.配置IIS服务3.添加防火墙安全策略4.使用cpolar内网穿透实现公网访问4.1 登录cpolar web ui管理界面4.2 启动website隧道4.3 获取公网URL地址4.4. 公网远程访问内网web站点4.5 配置固定二级子域名公网访问内网web站点4.5.1创建一条固定…

StructStreaming Batch mode和Continuous mode

StructStreaming Batch mode和Continuous mode 让我们把目光集中到 Structured Streaming&#xff0c;也就是流处理引擎本身。Structured Streaming 与 Spark MLlib 并列&#xff0c;是 Spark 重要的子框架之一。值得一提的是&#xff0c;Structured Streaming 天然能够享受 S…

C语言刷题总结

1.网购问题 &#xff08;1)这道题目需要分多种情况进行考虑&#xff1a;双11还是双12&#xff0c;有无优惠券&#xff0c;是否会出现优惠券的面值大于购买商品的单价&#xff08;这个时候直接按0元进行处理&#xff09;&#xff1b; &#xff08;2&#xff09;在对于优惠券的分…

Ansible-3

block任务块&#xff1a;可以通过block关键字&#xff0c;将多个任务组合到一起&#xff1b;将整个block任务组一起控制是否要执行。 如果test组中的主机系统发行版是Redhat则安装并启动httpd。原本这是需要两个任务安装和执行&#xff0c;通过block整合为一个任务执行。 rescu…