代碼隨想錄算法訓練營|第五十八天|583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇。刷题心得(c++)
目录
讀題
583. 两个字符串的删除操作
自己看到题目的第一想法
看完代码随想录之后的想法
72. 编辑距离
看完代码随想录之后的想法
583. 两个字符串的删除操作 - 實作
思路
代碼隨想錄思路
Code
72. 编辑距离 - 實作
思路
Code
编辑距离总结篇
判斷子序列
不同的子序列
兩個字符串的刪除操作
編輯距離
總結
判斷子序列
不同子序列
兩個字符串的刪除操作
編輯距離
讀題
583. 两个字符串的删除操作
自己看到题目的第一想法
如果今天可以兩個都刪除,那在w1[i - 1] 以及 w2[j - 1]的狀況下有三種狀況,兩者匹配,dp[i - 1][j - 1],不使用w1[i - 1]→dp[i - 1][j] 不使用w2[j - 1] → dp[i][j - 1],有用畫圖的方式嘗試理解但仍然無法推出狀態的改變。
看完代码随想录之后的想法
看完之後,才真正了解自己哪裡錯了,首先下標就定義錯了,下標應該是dp[i][j] w1[i - 1]為結尾以及w2[j - 1]為結尾如果想要達到相等,所需要刪除元素的最少次數為dp[i][j]
根據這個定義,如果相等的時候,不用刪除元素,那就會等於不包含當前i - 1 j - 1的 i - 2 j - 2,也就是dp[i][j] = dp[i - 1][j - 1]
如果不相等,則會有三種狀況可以刪除w1 最少操作次數就是不包含當前的w[i - 1]的狀況也就是dp[i - 1][j] + 1 也可以選擇刪除w2 最少操作次數是dp[i][j - 1] + 1,不包含當前w2[j - 1]的最少狀況。
也可以兩個都刪除,也就是dp[i - 1][j - 1] + 2,但這個我們可以思考為,之前的兩種狀況就有包含了,如果刪除w1,那是取不包含w1[i - 1]的狀況,換言之,就是刪除w1[i - 1]的狀況是dp[i - 1][j] ,在這個基礎上再減去w2[j - 1]這一個數就是dp[i - 1][j] + 1。
最後可以簡化為dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);
72. 编辑距离
看完代码随想录之后的想法
非常清晰,基本上有寫過之前的題目就會知道其中的門道,跟上一題一樣,先定義好dp[i][j]的定義,在下標word1[i - 1]以及下標word2[j-1],使其相同的最小編輯距離為dp[i][j]。
那就一樣會有兩種狀況相同與不相同
相同的話就是dp[i][j] = dp[i - 1][j - 1]代表不需要任何操作,跟上一次不包含word1[i - 1]以及word2[j - 1]的狀況一致
不相同的話要做增刪換
增和刪可以想成同樣一個,操作數都是一樣的,引用代碼隨想錄中提到的例子
word2添加一个元素,相当于word1删除一个元素,例如
word1 = "ad" ,word2 = "a"
,word1
删除元素'd'
和word2
添加一个元素'd'
,变成word1="a", word2="ad"
, 最终的操作数是一样! dp数组如下图所示意的:0 a 0 a d+-----+-----+ +-----+-----+-----+0 | 0 | 1 | 0 | 0 | 1 | 2 |+-----+-----+ ===> +-----+-----+-----+a | 1 | 0 | a | 1 | 0 | 1 |+-----+-----+ +-----+-----+-----+d | 2 | 1 |+-----+-----+
替換的話代表只需要替換其中一個數就可以一致,那就會是dp[i][j] = dp[i - 1][j - 1] + 1,代表我只要替換word1 或者word2就可以使得兩者相同。使用dp[i - 1][j - 1]的緣故是,這個數不包含word1、或word2,所以如果只需要替換一個數就可以達成,那就是將這個數加一就好
583. 两个字符串的删除操作 - 實作
思路
-
定義DP數組以及下標的含意
i - 1 下標的word1以及 j - 1 下標的word2,要達到相同的子序列最少需要刪除多少次為dp[i][j]
-
遞推公式
分成兩種狀態相同與不相同
相同的話代表不用刪除,也就是dp[i - 1][j - 1]即為上一次不包含當前兩個數的狀況
不相同的話有三種狀況
- 刪除word1
- 代表不包含當前word1的狀況在加上一個刪除的個數也就是dp[i - 1][j] + 1
- 刪除word2
- 代表不包含當前word2的狀況再加上1個刪除數,也就是dp[i][j - 1] + 1
- 刪除word1、word2
- 代表不包含當前word1、word2的狀況加上兩個刪除數,也就是dp[i - 1][j - 1] + 2
- 但可以換個角度來看,如果刪除word1或word2時,我們要先得知不包含word1或word2的狀況,也就是dp[i - 1][j] 或 dp[i][j - 1] 也就是說這兩個狀態組都代表已經忽略word1 以及word 2時,當前的狀況,那在這個基礎上再加1,也可以理解為在忽略word1的狀況下在刪除word2 就會是將word1、word2都刪除的狀況,也就是dp[i - 1][j] + 1。
- 刪除word1
-
根據遞推公式、題意以及定義,確定DP數組如何初始化
因為兩者都可以刪除,所以在初始話時,空字符串都是0,因為不用刪除,其他的部分則根據當前的位置,刪除不同數量的word即可以成為空字符串,也就是要刪除i 個或j個字,字符串才會為空
-
確定遍歷順序
因為需要左上角的數據來進行遍歷,所以是由前往後。
代碼隨想錄思路
Code
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++) dp[i][0] = i;for(int j = 0; j <= word2.size(); j++) dp[0][j] = j;for(int i = 1; i <= word1.size(); i++) {for(int j = 1; j <= word2.size(); j++) {if(word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];else dp[i][j] = min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);}}return dp[word1.size()][word2.size()];}
};
72. 编辑距离 - 實作
思路
-
定義DP數組以及下標的含意
i - 1 下標的word1以及 j - 1 下標的word2,要達到相同的子序列最少需要編輯多少次為dp[i][j]
-
遞推公式
分成兩種狀態相同與不相同
相同的話代表不用編輯,也就是dp[i - 1][j - 1]即為上一次不包含當前兩個數的狀況
不相同的話有三種狀況,取最小的
- 刪除\添加 word1
- 代表不包含當前word1的狀況在加上一個刪除\添加的個數也就是dp[i - 1][j] + 1
- 刪除\添加 word2
- 代表不包含當前word2的狀況再加上1個刪除\添加數,也就是dp[i][j - 1] + 1
- 替換
- 代表不包含當前word1、word2的狀況加上一個操作,也就是dp[i - 1][j - 1] + 1
- 刪除\添加 word1
-
根據遞推公式、題意以及定義,確定DP數組如何初始化
當j - 1以及 i - 1的word1、word2需要初始化時,需要刪除i個或j個字符才會等於空字符
-
確定遍歷順序
總共有四個遞推公式
dp[i][j] = dp[i - 1][j - 1]
dp[i][j] = dp[i - 1][j - 1] + 1
dp[i][j] = dp[i - 1][j] + 1
dp[i][j] = dp[i][j - 1] + 1
因為需要左上角的數據來進行遍歷,所以是由前往後。
Code
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][0] = i;for(int j = 0; j <= word2.size(); j++) dp[0][j] = j;for(int i = 1; i <= word1.size(); i++) {for(int j = 1; j <= word2.size(); j++) {if(word1[i - 1] == word2[j - 1]) dp[i][j] = dp[i - 1][j - 1];else dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;}}return dp[word1.size()][word2.size()];}
};
编辑距离总结篇
判斷子序列
定義: dp[i][j] 代表 i - 1 的s 和 j - 1 的t 相同子序列的長度為dp[i][j]
根據這個定義,我們可以知道當兩者相同時,長度要加一
如果不相等時,則可以視為忽略當下的t[j - 1]取t的前一個數也就是t[j - 2] → dp[i][j] = dp[i][j - 1]
不同的子序列
定義: dp[i][j]: 以i - 1為結尾s子序列當中,出現以j - 1為結尾t的個數為dp[i][j]
根據定義
-
兩者相等時有兩種狀況
我可以使用s[i - 1]也可以不使用s[i - 1] 因為定義是i - 1為結尾的s子序列中,出現以j - 1為結尾的t個數
所以在使用s[i - 1]的狀況,我不用刪除任何元素,所以我的值會是dp[i - 1][j - 1]即上一次的狀況,
如果不使用s[i - 1]的狀況,我等同於只需要不考慮s[i - 1] 但t[j - 1]仍然在,所以值會是dp[i - 1][j]
相同時的轉移方程就會是dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
-
兩者不相等時相當於s 要刪除元素,因為 s的字符串中,這個位置並沒有t的字串,所以要刪除
如果是s要刪除元素,那就是取s[i - 2] 這個不包含s[ i -1]的最大值,但t是要比較的子序列,所以t不用動,也就是說這個dp[i][j]會是由s[i - 2]t[j - 1]所組成,所對應的dp數組是dp[i][j] = dp[i - 1][j]。
初始化:
dp[i][0] 一定都是1,因為把s全部刪除後出現空字符的個數就是一
dp[0][j] 因為s無論如何都無法變成t,所以都是0
dp[0][0] 空字符串s可以刪除0個元素變成空字符串t,所以等於1
兩個字符串的刪除操作
定義: i - 1 下標的word1以及 j - 1 下標的word2,要達到相同的子序列最少需要刪除多少次為dp[i][j]
根據這個定義轉移方程會有兩個狀況
- 兩者相同
相同的話代表不用刪除,也就是dp[i - 1][j - 1]即為上一次不包含當前兩個數的狀況
- 兩者不相同
不相同的話有三種狀況
- 刪除word1
- 代表不包含當前word1的狀況在加上一個刪除的個數也就是dp[i - 1][j] + 1
- 刪除word2
- 代表不包含當前word2的狀況再加上1個刪除數,也就是dp[i][j - 1] + 1
- 刪除word1、word2
- 代表要不包含word1以及word2的值,也就是dp[i - 1][j - 1] ,並加上刪除兩次,所以是dp[i - 1][j - 1] + 2
- 但也可以想成取word1不存在的部分也就是dp[i - 1][j],並刪除word2,也就是dp[i - 1][j] + 1,反之也可以想成word2不存在。
- 那因為我們要找出最少需要刪除多少次,所以就是取刪除狀況中最小的數值+1
狀態轉移方程就會是 dp[i][j] = min(dp[i - 1][j], dp[i][j - 1]) + 1;
初始化的部分就是要如何將i - 1結尾的word1以及j - 1結尾的word2 刪除至空字符串,就會需要i, j 次的刪除次數才行。
編輯距離
定義: i - 1 下標的word1以及 j - 1 下標的word2,要達到相同的子序列最少需要操作多少次為dp[i][j]
這一題其實就是前面的部分,只是要想明白相同時要做甚麼、不相同時要做甚麼
如果相同,則不操作
不相同則需要找出最小的增、刪、替換的方案
增加跟刪除可以想成同一個操作數
- 需要增刪word1時,都是取dp[i - 1][j] + 1
- 需要增刪word2時,都是取dp[i][j - 1] + 1
- 至於增刪word1、word2則跟之前一樣,可以簡化成上述的兩個式子
- 需要替換word1或word2的話,則需要取這兩個都不存在的部分加上一次操作數也就是dp[i - 1][j - 1] + 1
所以得出四個轉移方程
if(word1[i - 1] == word2[j - 1])
dp[i][j] = dp[i - 1][j - 1];
else
dp[i][j] = min(min(dp[i - 1][j], dp[i][j - 1]), dp[i - 1][j - 1]) + 1;
總結
在編輯距離的題目當中,有個很重要的核心就是定義好dp[i][j]的定義,在根據這個定義,去推導出公式以及初始化的方式
其實前三題很重要的思維就是對於刪除的理解,在不同的定義上刪除的做法都不太一樣
判斷子序列
刪除是dp[i][j - 1],忽略前一個t
不同子序列
使用s[i - 1]的,我不用刪除任何元素,所以值會是dp[i - 1][j - 1]即上一次的狀況,
如果不使用s[i - 1]的狀況,我等同於只需要不考慮s[i - 1] 但t[j - 1]仍然在,所以值會是dp[i - 1][j]
相同時的轉移方程就會是dp[i][j] = dp[i - 1][j - 1] + dp[i - 1][j];
兩者不相等時相當於s 要刪除元素,因為 s的字符串中,這個位置並沒有t的字串,所以要刪除
如果是s要刪除元素,那就是取s[i - 2] 這個不包含s[ i -1]的最大值,但t是要比較的子序列,所以t不用動,也就是說這個dp[i][j]會是由s[i - 2]t[j - 1]所組成,所對應的dp數組是dp[i][j] = dp[i - 1][j]。
兩個字符串的刪除操作
- 刪除word1
- 代表不包含當前word1的狀況在加上一個刪除的個數也就是dp[i - 1][j] + 1
- 刪除word2
- 代表不包含當前word2的狀況再加上1個刪除數,也就是dp[i][j - 1] + 1
- 刪除word1、word2
- 代表要不包含word1以及word2的值,也就是dp[i - 1][j - 1] ,並加上刪除兩次,所以是dp[i - 1][j - 1] + 2
編輯距離
所謂的增刪基本上是同一個操作數,只是需要明確甚麼是替換,以及下標定義為何
- 需要增刪word1時,都是取dp[i - 1][j] + 1
- 需要增刪word2時,都是取dp[i][j - 1] + 1
- 需要替換word1或word2的話,則需要取這兩個都不存在的部分加上一次操作數也就是dp[i - 1][j - 1] + 1
整體而言編輯距離透過這幾天的理解過後,透過這次的總結,對於這類題目有更深的了解了。
相关文章:
代碼隨想錄算法訓練營|第五十八天|583. 两个字符串的删除操作、72. 编辑距离、编辑距离总结篇。刷题心得(c++)
目录 讀題 583. 两个字符串的删除操作 自己看到题目的第一想法 看完代码随想录之后的想法 72. 编辑距离 看完代码随想录之后的想法 583. 两个字符串的删除操作 - 實作 思路 代碼隨想錄思路 Code 72. 编辑距离 - 實作 思路 Code 编辑距离总结篇 判斷子序列 不同…...

JavaScript基础之BOM与DOM
文章目录 BOM操作window对象window的子对象之navigator对象(了解即可)window的子对象之screen对象(了解即可)window的子对象之history对象(了解即可)window的子对象之location对象 弹出框警告框确认框提示框…...

【Linux学习笔记】进程概念(中)
1. 操作系统的进程状态2. Linux操作系统的进程状态3. 僵尸进程4. 孤儿进程5. 进程优先级5.1. 优先级是什么和为什么要有优先级5.2. Linux中的进程优先级 6. 进程切换7. 环境变量7.1. 环境变量的认识7.2. 环境变量相关的命令7.3. 环境变量和本地变量7.4. 命令行参数7.5. 获取环境…...

scanpy赋值问题
今天发现一个很奇怪的bug import numpy as np import pandas as pd import anndata as ad from scipy.sparse import csr_matrix print(ad.__version__)counts csr_matrix(np.random.poisson(1, size(100, 2000)), dtypenp.float32) adata1 ad.AnnData(counts) print(adata1)…...

腾讯云域名备案后,如何解析到华为云服务器Linux宝塔面板
一、购买域名并且进行备案和解析,正常情况下,购买完域名,如果找不到去哪备案,可以在腾讯云上搜索“备案”关键词就会出现了,所以这里不做详细介绍,直接进行步骤提示: 二、申请ssl证书࿰…...
odoo 按钮打印pdf报表
odoo打印一般是在动作里面进行的 所以此方法可用自定义按钮进行打印 <template id"report_sale_line_packing_template"> xxx </template><template id"report_sale_line_packing"><t t-call"web.basic_layout"><t …...

用逻辑分析仪观察串口Uart数据波形
一、概述 只讨论嵌入式编程中较为常用的异步串行接口(Universal Asynchronous Receiver/Transmitter, UART),TTL电平。 串口的参数一般有: 1.波特率,数据传输速率,单位bps(bits per…...
数据结构-栈应用括号匹配
1、顺序栈的定义 2、顺序栈的入栈,出栈,取出栈顶元素,匹配判断函数 3、顺序栈的运行测试 4、实现代码 #include<iostream> using namespace std; #define OK 1 #define ERROR 0 #define OVERFLOW -2 typedef int Status; #define M…...
leetcode做题笔记209. 长度最小的子数组
给定一个含有 n 个正整数的数组和一个正整数 target 。 找出该数组中满足其总和大于等于 target 的长度最小的 连续子数组 [numsl, numsl1, ..., numsr-1, numsr] ,并返回其长度。如果不存在符合条件的子数组,返回 0 。 示例 1: 输入&#…...

【机器学习】几种常用的机器学习调参方法
在机器学习中,模型的性能往往受到模型的超参数、数据的质量、特征选择等因素影响。其中,模型的超参数调整是模型优化中最重要的环节之一。超参数(Hyperparameters)在机器学习算法中需要人为设定,它们不能直接从训练数据…...

使用免费 FlaskAPI 部署 YOLOv8
目标检测和实例分割是计算机视觉中关键的任务,使计算机能够在图像和视频中识别和定位物体。YOLOv8是一种先进的、实时的目标检测系统,因其速度和准确性而备受欢迎。 Flask是一个轻量级的Python Web框架,简化了Web应用程序的开发。通过结合Fla…...

不使用屏幕在树莓派4B安装Ubuntu22.04桌面版(64位)
因为时间有限只说一下基本路径: 1首先安装Ubuntu22.04server版本 2设置服务器版本的SSH和WiFi 3通过服务器版本安装Ubuntu-desktop升级到Ubuntu22.04桌面版 4在桌面版上安装远程控制软件:xrdp; 5使用Windows自带的远程桌面连接访问Ubuntu 6完成...

Pymysql模块使用操作
一、pymysql模块安装 二、测试数据库连接 测试数据库连接.py from pymysql import Connectioncon None try:# 创建数据库连接con Connection(host"localhost",port3306,user"root",password"XXXXX")# 测试链接print(con.get_host_info())print…...

8+双疾病+WGCNA+多机器学习筛选疾病的共同靶点并验证表达
今天给同学们分享一篇双疾病WGCNA多机器学习的生信文章“Shared diagnostic genes and potential mechanism between PCOS and recurrent implantation failure revealed by integrated transcriptomic analysis and machine learning”,这篇文章于2023年5月16日发表…...
springboot如何获取前端请求头的值并加入ThreadLocal
依赖: <dependency><groupId>org.aspectj</groupId><artifactId>aspectjweaver</artifactId><version>1.9.7</version> </dependency>示例: public class ThreadLocalUtil {private static ThreadLoc…...

程序员想要网上接单却看花了眼?那这几个平台你可得收藏好了!
现在经济压力这么大,但是生活成本还在上升,相信大家都知道“四脚吞金兽”的威力了吧!话虽如此,但是生活总得继续,为了家庭的和谐幸福,为了孩子的未来,不少人选择多干几份工作,赚点外…...
前端食堂技术周刊第 102 期:Next.js 14、Yarn 4.0、State of HTML、SEO 从 0 到 1
美味值:🌟🌟🌟🌟🌟 口味:肥牛宽粉 食堂技术周刊仓库地址:https://github.com/Geekhyt/weekly 大家好,我是童欧巴。欢迎来到前端食堂技术周刊,我们先来看下…...

GPT与人类共生:解析AI助手的兴起
随着GPT模型的崭新应用,如百度的1和CSDN的2,以及AI助手的普及,人们开始讨论AI对就业市场和互联网公司的潜在影响。本文将探讨GPT和AI助手的共生关系,以及我们如何使用它们,以及使用的平台和动机。 GPT和AI助手…...

HTML脚本、字符实体、URL
HTML脚本: JavaScript 使 HTML 页面具有更强的动态和交互性。 <script> 标签用于定义客户端脚本,比如 JavaScript。<script> 元素既可包含脚本语句,也可通过 src 属性指向外部脚本文件。 JavaScript 最常用于图片操作、表单验…...
UOS安装Jenkins
一,环境准备 1.安装jdk 直接使用命令行(sudo apt install -y openjdk-11-jdk)安装jdk11 2.安装maven 参考此篇文章即可 UOS安装并配置Maven工具_uos 安装maven_蓝天下的一员的博客-CSDN博客 不过要注意这篇文章有个小错误,我…...
vscode里如何用git
打开vs终端执行如下: 1 初始化 Git 仓库(如果尚未初始化) git init 2 添加文件到 Git 仓库 git add . 3 使用 git commit 命令来提交你的更改。确保在提交时加上一个有用的消息。 git commit -m "备注信息" 4 …...
<6>-MySQL表的增删查改
目录 一,create(创建表) 二,retrieve(查询表) 1,select列 2,where条件 三,update(更新表) 四,delete(删除表…...

UE5 学习系列(三)创建和移动物体
这篇博客是该系列的第三篇,是在之前两篇博客的基础上展开,主要介绍如何在操作界面中创建和拖动物体,这篇博客跟随的视频链接如下: B 站视频:s03-创建和移动物体 如果你不打算开之前的博客并且对UE5 比较熟的话按照以…...

DIY|Mac 搭建 ESP-IDF 开发环境及编译小智 AI
前一阵子在百度 AI 开发者大会上,看到基于小智 AI DIY 玩具的演示,感觉有点意思,想着自己也来试试。 如果只是想烧录现成的固件,乐鑫官方除了提供了 Windows 版本的 Flash 下载工具 之外,还提供了基于网页版的 ESP LA…...
今日学习:Spring线程池|并发修改异常|链路丢失|登录续期|VIP过期策略|数值类缓存
文章目录 优雅版线程池ThreadPoolTaskExecutor和ThreadPoolTaskExecutor的装饰器并发修改异常并发修改异常简介实现机制设计原因及意义 使用线程池造成的链路丢失问题线程池导致的链路丢失问题发生原因 常见解决方法更好的解决方法设计精妙之处 登录续期登录续期常见实现方式特…...

均衡后的SNRSINR
本文主要摘自参考文献中的前两篇,相关文献中经常会出现MIMO检测后的SINR不过一直没有找到相关数学推到过程,其中文献[1]中给出了相关原理在此仅做记录。 1. 系统模型 复信道模型 n t n_t nt 根发送天线, n r n_r nr 根接收天线的 MIMO 系…...

技术栈RabbitMq的介绍和使用
目录 1. 什么是消息队列?2. 消息队列的优点3. RabbitMQ 消息队列概述4. RabbitMQ 安装5. Exchange 四种类型5.1 direct 精准匹配5.2 fanout 广播5.3 topic 正则匹配 6. RabbitMQ 队列模式6.1 简单队列模式6.2 工作队列模式6.3 发布/订阅模式6.4 路由模式6.5 主题模式…...
快刀集(1): 一刀斩断视频片头广告
一刀流:用一个简单脚本,秒杀视频片头广告,还你清爽观影体验。 1. 引子 作为一个爱生活、爱学习、爱收藏高清资源的老码农,平时写代码之余看看电影、补补片,是再正常不过的事。 电影嘛,要沉浸,…...

Linux nano命令的基本使用
参考资料 GNU nanoを使いこなすnano基础 目录 一. 简介二. 文件打开2.1 普通方式打开文件2.2 只读方式打开文件 三. 文件查看3.1 打开文件时,显示行号3.2 翻页查看 四. 文件编辑4.1 Ctrl K 复制 和 Ctrl U 粘贴4.2 Alt/Esc U 撤回 五. 文件保存与退出5.1 Ctrl …...

FFmpeg:Windows系统小白安装及其使用
一、安装 1.访问官网 Download FFmpeg 2.点击版本目录 3.选择版本点击安装 注意这里选择的是【release buids】,注意左上角标题 例如我安装在目录 F:\FFmpeg 4.解压 5.添加环境变量 把你解压后的bin目录(即exe所在文件夹)加入系统变量…...