583.两个字符串的删除操作 72.编辑距离

583.两个字符串的删除操作 72.编辑距离

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

力扣题目链接(opens new window)

给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。

示例:

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

思路

思路:动态规划
动态规划五部曲
1.定义dp数组以及下标含义
定义二维dp数组。dp[i][j]表示以字符word1[i]为结尾字符串和以字符word2 [j]为结尾字符串中,相同所需的最小步数
2。定义递推公式
情况一:word1[i] == word2 [j]
dp[i][j] = dp[i-1][j-1]
情况二:word1[i] != word2 [j]
dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);
3.初始化dp数组
考虑二维数组第一行和第一列如何初始化
第一行
第一个元素
if (word1.charAt(0) != word2.charAt(0)) {dp[0][0] = 2;
}
剩余元素
如果word1.charAt(i) == word2.charAt(0),删除字符步数为i
如果word1.charAt(i) != word2.charAt(0),【删除字符步数】跟【dp[0][0]】也就是word1.charAt(i) == word2.charAt(0)是否相等有关
1.相等。那么删除字符步数为dp[i][0] = i。举例如下 word1:abc word2:a.
dp[0][0] = 0.dp[1][0]表示删除ab等于a的步数,很显然为1,也就是i
可以得出dp[i][0] = i
2.不相等。那么删除字符步骤相比dp[i-1][0]应增加1.举例如下 word1:abc word2:t
dp[0][0] = 2.dp[1][0]表示删除ab等于t的步数,很显然为3,也就是dp[0][0] +1
可以得出dp[1][0] = dp[0][0] +1.即 dp[i][0] = dp[i - 1][0] + 1;
for (int i = 1; i < word1.length(); i++) {if (word1.charAt(i) == word2.charAt(0)) {dp[i][0] = i;} else {if (dp[0][0] == 0) {dp[i][0] = i;} else {dp[i][0] = dp[i - 1][0] + 1;}}}第一列 同理
4.遍历顺序
有递推公式可知
从小到大遍历即可
5.举例推导dp数组
时间复杂度O(N^2)
空间复杂度O(N^2)

代码如下

public static void main(String args[]) {minDistance("sea", "ate");
}public static int minDistance(String word1, String word2) {if (word1 == null || word2 == null)// 边界条件处理return 0;if (word1.equals("") && !word2.equals(""))return word2.length();if ((!word1.equals("") && word2.equals("")))return word1.length();int[][] dp = new int[word1.length()][word2.length()];// 定义Dp数组以及初始化if (word1.charAt(0) != word2.charAt(0)) {dp[0][0] = 2;}for (int i = 1; i < word1.length(); i++) {if (word1.charAt(i) == word2.charAt(0)) {dp[i][0] = i;} else {if (dp[0][0] == 0) {dp[i][0] = i;} else {dp[i][0] = dp[i - 1][0] + 1;}}}for (int j = 1; j < word2.length(); j++) {if (word2.charAt(j) == word1.charAt(0)) {dp[0][j] = j;} else {if (dp[0][0] == 0) {dp[0][j] = j;} else {dp[0][j] = dp[0][j - 1] + 1;}}}for (int i = 1; i < word1.length(); i++) {for (int j = 1; j < word2.length(); j++) {if (word1.charAt(i) == word2.charAt(j)) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);}}}return dp[word1.length() - 1][word2.length() - 1];}

问题

问题1
本题目在推导dp公式时出现了错误
错误推导方式
情况二:word1[i] != word2 [j]
dp[i][j] = Math.min(dp[i-1][j],dp[i][j-1]);
正确方式
忘记给步数加一了
dp[i][j] = Math.min(dp[i-1][j] + 1,dp[i][j-1] + 1);问题2
初始化错误,初始化有点复杂
错误方式
没考虑到word1.charAt(i) != word2.charAt(0)时
【删除字符步数dp[i][0]】跟【dp[0][0]】有关

优化

本题目属于编辑距离类题目。只有删除操作,对word1和word2都有删除操作
二刷时采用另一种定义dp数组的方式、
dp[i][j]表示以word1[i-1]和word2[i-1]为结尾字符串中,使得 word1 和 word2 相同所需的最小步数
采用这种定义dp数组方式,可简化初始化dp数组流程
从递推公式中,可以看出来,dp[i][0] 和 dp[0][j]是一定要初始化的。
dp[i][0]:word2为空字符串,以i-1为结尾的字符串word1要删除多少个元素,才能和word2相同呢,很明显dp[i][0] = i。
dp[0][j]的话同理

代码如下

public static int minDistance(String word1, String word2) {if (word1 == null || word2 == null)return 0;int[][] dp = new int[word1.length() + 1][word2.length() + 1];// 定义Dp数组以及初始化for (int i = 0; i <= word1.length(); i++) {dp[i][0] = i;}for (int j = 0; j <= word2.length(); j++) {dp[0][j] = j;}for (int i = 1; i <= word1.length(); i++) {for (int j = 1; j <= word2.length(); j++) {if (word1.charAt(i - 1) == word2.charAt(j - 1)) {dp[i][j] = dp[i - 1][j - 1];} else {dp[i][j] = Math.min(dp[i - 1][j] + 1, dp[i][j - 1] + 1);}}}return dp[word1.length()][word2.length()];}

72.编辑距离

力扣题目链接(opens new window)

给你两个单词 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 由小写英文字母组成

思路

思路:动态规划
动态规划五部曲
1.定义dp数组以及下标含义
定义二维dp数组。dp[i][j]表示以字符word1[i-1]为结尾字符串和以字符word2 [j-1]为结尾字符串中,word1 转换成 word2 所使用的最少操作数 。
2.定义递推公式
word1[i-1] == word2 [j-1].dp[i][j] = dp[i-1][j-1]
word1[i-1] != word2 [j-1].对word1有增删改三种操作
word1删除操作 dp[i][j] = dp[i-1][j] + 1;
word1增加操作 dp[i][j] = dp[i + 1][j] + 1 = dp[i][j - 1] + 1;
word1修改操作 dp[i][j] = dp[i - 1][j - 1] + 1;
这里解释下word1增加操作递推公式怎么推导
当word1字符串尾部新增元素后,长度由i 变为 i + 1.那么dp[i][j] = dp[i + 1][j] + 1.但如果这么写的话,dp[i][j]就要先得到dp[i+1]的值才能推导出来
很显然和删除修改操作的dp公式存在冲突,这两个公式都是先得到dp[i - 1]的值后推导dp[i][j]。需要把dp[i + 1][j] 转换成跟 i-1有关的dp公式
word1添加一个元素,相当于word2删除一个元素,例如 word1 = "a" ,word2 = "ad",word1添加元素'd' 和 word2删除一个元素'd',变成word1="ad", word2="a", 最终的操作数是一样!
所以word1增加操作 dp[i][j] = dp[i + 1][j] + 1 = dp[i][j - 1] + 1;
3.初始化dp数组
dp[i][0] 和 dp[0][j] 表示什么呢?
dp[i][0] :以下标i-1为结尾的字符串word1,和空字符串word2,最近编辑距离为dp[i][0]。
那么dp[i][0]就应该是i,对word1里的元素全部做删除操作,即:dp[i][0] = i;
同理dp[0][j] = j;
4.遍历顺序
有递推公式可知
从小到大遍历即可
5.举例推导dp数组

代码如下

// 时间复杂度O(N^2)
// 空间复杂度O(N^2)
public int minDistance(String word1, String word2) {int[][] dp = new int[word1.length() + 1][word2.length() + 1];for (int i = 0; i <= word1.length(); i++) {dp[i][0] = i;}for (int j = 0; j <= word2.length(); j++) {dp[0][j] = j;}for (int i = 1; i <= word1.length(); i++) {for (int j = 1; j <= word2.length(); j++) {if (word1.charAt(i-1) == word2.charAt(j-1))dp[i][j] = dp[i - 1][j - 1];else {dp[i][j] = Math.min(dp[i][j - 1], dp[i - 1][j]) + 1;}}}return dp[word1.length()][word2.length()];}

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

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

相关文章

dubbo项目发布时Destroyed异常分析

1、问题现象 在发布项目时&#xff0c;elk有打印use dubbo version 2.6.2 is DESTROYED, can not be invoked any more!相关的报错日志&#xff0c;来提示dubbo消费者调用生产者时&#xff0c;生产者服务已经DESTROYED。 ChatGpt可知&#xff1a; 2、问题溯源 com.alibaba.dub…

序列到序列模型

一.序列到序列模型的简介 序列到序列&#xff08;Sequence-to-Sequence&#xff0c;Seq2Seq&#xff09;模型是一类用于处理序列数据的深度学习模型。该模型最初被设计用于机器翻译&#xff0c;但后来在各种自然语言处理和其他领域的任务中得到了广泛应用。 Seq2Seq模型的核…

怎样通过powershell 打开win10的自动更新?

要通过PowerShell命令打开Windows 10的自动更新&#xff0c;可以按照以下步骤操作&#xff1a; 打开PowerShell&#xff1a;在Windows 10中&#xff0c;点击“开始”按钮&#xff0c;输入“PowerShell”&#xff0c;然后选择“Windows PowerShell”。 以管理员身份运行PowerSh…

【软件测试学习笔记6】Linux常用命令

格式 command [-options] [parameter] command 表示的是命令的名称 []表示是可选的&#xff0c;可有可无 [-options]&#xff1a;表示的是命令的选项&#xff0c;可有一个或多个&#xff0c;也可以没有 [parameter]&#xff1a;表示命令的参数&#xff0c;可以有一个或多…

VLAN区域间路由详解

LAN局域网 WAN 广域网 WLAN无线局域网 VLAN:虚拟局域网 交换机和路由器&#xff0c;协同工作后&#xff0c;将原来的一个广播域&#xff0c;切分为多个&#xff0c;节省硬件成本&#xff1b; 配置思路&#xff1a; 交换机上创建vlan交换机上的各个接口划分到对应的vlan中 T…

微信小程序页面传值的几种方式

1.URL参数传值&#xff1a;通过在跳转链接中附加参数&#xff0c;在目标页面的onLoad函数中获取参数。 2.全局变量&#xff1a;通过在app.js文件中定义全局变量&#xff0c;在源页面设置变量的值&#xff0c;目标页面通过getApp().globalData获取变量的值。 3.缓存存储&#xf…

flink源码分析 - yaml解析

flink版本: flink-1.12.1 代码位置: org.apache.flink.configuration.GlobalConfiguration 主要看下解析yaml文件的方法: org.apache.flink.configuration.GlobalConfiguration#loadYAMLResource /** Licensed to the Apache Software Foundation (ASF) under one* or…

尚无忧【无人共享空间 saas 系统源码】无人共享棋牌室系统源码共享自习室系统源码,共享茶室系统源码

可saas多开&#xff0c;非常方便&#xff0c;大大降低了上线成本 UNIAPPthinkphpmysql 独立开源&#xff01; 1、定位功能&#xff1a;可定位附近是否有店 2、能通过关键字搜索现有的店铺 3、个性轮播图展示&#xff0c;系统公告消息提醒 4、个性化功能展示&#xff0c;智能…

LED车灯电源解决方案SCT8162x、SCT2464Q、SCT71403Q、SCT71405Q、SCT53600等

随着LED封装技术的成熟和成本的下降&#xff0c;LED车灯渗透率迅速提升。车灯控制技术不断向节能化、智能化和个性化方向发展。ADB大灯配置门槛下探&#xff0c;像素数据急剧增加&#xff0c;LED 数量不断增加&#xff0c;陆续有智能车灯达到百万级像素&#xff0c;且动画效果需…

【算法小记】深度学习——循环神经网络相关原理与RNN、LSTM算法的使用

文中程序以Tensorflow-2.6.0为例 部分概念包含笔者个人理解&#xff0c;如有遗漏或错误&#xff0c;欢迎评论或私信指正。 卷积神经网络在图像领域取得了良好的效果&#xff0c;卷积核凭借优秀的特征提取能力通过深层的卷积操作可是实现对矩形张量的复杂计算处理。但是生活中除…

前端——框架——Vue

提示&#xff1a; 本文只是从宏观角度简要地梳理一遍vue3&#xff0c;不至于说学得乱七八糟、一头雾水、不知南北&#xff0c;如果要上手写代码、撸细节&#xff0c;可以根据文中的关键词去查找资料 简问简答&#xff1a; vue.js是指vue3还是vue2&#xff1f; Vue.js通常指的是…

DNS - 全家桶(114 DNS、阿里DNS、百度DNS 、360 DNS、Google DNS)

DNS是什么&#xff1f; DNS是域名系统,Domain Name System的缩写,是一个服务。 DNS就是把域名解析为IP地址&#xff0c;提供我们上网&#xff0c;我们能够上网最终是找到IP地址。 比如&#xff0c;http://xxxx.com是域名&#xff0c;那么他的IP地址假设是144.144.144.144&am…

网络安全中的人工智能:保护未来数字世界的利剑

随着现代社会的数字化进程不断推进&#xff0c;网络安全问题变得日益严峻。为了更好地应对日益复杂的网络威胁&#xff0c;人工智能&#xff08;AI&#xff09;技术正被广泛应用于网络安全领域。 在互联网的时代背景下&#xff0c;网络安全已成为国家和企业面临的一项重大挑战。…

Rust 错误处理(下)

目录 1、用 Result 处理可恢复的错误 1.1 传播错误的简写&#xff1a;? 运算符 1.2 哪里可以使用 ? 运算符 2、要不要 panic! 2.1 示例、代码原型和测试都非常适合 panic 2.2 当我们比编译器知道更多的情况 2.3 错误处理指导原则 2.4 创建自定义类型进行有效性验证 …

K8s面试题——情景篇

文章目录 一、考虑一家拥有分布式系统的跨国公司&#xff0c;拥有大量数据中心&#xff0c;虚拟机和许多从事各种任务的员工。您认为这样公司如何以与 Kubernetes 一致的方式管理所有任务?二、考虑一种情况&#xff0c;即公司希望通过维持最低成本来提高其效率和技术运营速度。…

uni-app 经验分享,从入门到离职(年度实战总结:经验篇)——上传图片以及小程序隐私保护指引设置

文章目录 &#x1f525;年度征文&#x1f4cb;前言⏬关于专栏 &#x1f3af;关于上传图片需求&#x1f3af;前置知识点和示例代码&#x1f9e9;uni.chooseImage()&#x1f9e9;uni.chooseMedia()&#x1f4cc;uni.chooseImage() 与 uni.chooseMedia() &#x1f9e9;uni.chooseF…

语义分割结果后处理与可视化:轮廓、中心点和重心标记

目标 介绍一个用于语义分割后处理和可视化的Python脚本。该脚本通过OpenCV库实现&#xff0c;可以在图像中标记出分割区域的轮廓、中心点和重心&#xff0c;以提供更直观的视觉反馈 import cv2 import numpy as npfilename ./mask/3.png # 读取灰度图像 gray_image cv2.imre…

【playwright】新一代自动化测试神器playwright+python系列课程14_playwright网页相关操作_获取网页标题和URL

Playwright 网页操作_获取网页标题和URL 在做web自动化测试时&#xff0c;脚本执行完成后需要进行断言&#xff0c;判断脚本执行是否存在问题。在断言时通常选择一些页面上的信息或者页面上元素的状态来断言&#xff0c;使用网页标题或url来断言就是常见的断言方式&#xff0c…

ssh:connect to host github.com port 22: Connection timed out

解决流程 1.将github的端口由22改为443 ssh -T -p 443 gitssh.github.com 2.接着输入yes进行确认 The authenticity of host [ssh.github.com]:443 ([192.168.1.100]:443) cant be established. TG45532 key fingerprint is SHA256:dfjeDFlkkfdfkDFKEidkfkDFkkKKdjFESDCFLE. …

Java-NIO篇章(2)——Buffer缓冲区详解

Buffer类简介 Buffer类是一个抽象类&#xff0c;对应于Java的主要数据类型&#xff0c;在NIO中有8种缓冲区类&#xff0c;分别如下&#xff1a; ByteBuffer、 CharBuffer、 DoubleBuffer、 FloatBuffer、 IntBuffer、 LongBuffer、 ShortBuffer、MappedByteBuffer。 本文以它的…