LeetCode刷题之HOT100之编辑距离

2024-06-08 15:28

本文主要是介绍LeetCode刷题之HOT100之编辑距离,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

吃了一份扬州炒饭,等会还要去喝点酒,今天室友生日,下午上课我才反应过来。先做道题再说。
2024/6/8 昨天去喝酒去了,这道题没有做。大概喝到凌晨一点,看了会《地下室手记》,简单洗漱后上床准备休憩。辗转无眠,凌晨五点 天见白,遂去旗山湖走了一圈。放几张风景照。
在这里插入图片描述

图一、渔人撑篙打渔,好不快意

在这里插入图片描述

图二 、旗山准备醒来

在这里插入图片描述

图三 、莲花睡在上面宁静、恬适

在这里插入图片描述

图四、湖光山色,甚美
Anyway,景色看过,那么接下来就做做题。

1、题目描述

在这里插入图片描述

2、逻辑分析

这题以前是hard啊,现在反而被降级了。我是说怎么看不懂,题解也有些看不懂啊。GPT如是说:
算法原理:编辑距离是衡量两个字符串差异的一种指标,表示通过插入、删除和替换操作将一个字符串转换成另一个字符串所需要的最少编辑次数。
步骤:

  1. 初始化:
    如果其中一个字符串为空,那么编辑距离就等于非空字符串的长度,因为需要将空字符串填充成另一个字符串,这需要进行与另一个字符串长度相等的插入操作。

  2. 动态规划:
    这个问题可以使用动态规划(DP)来解决。DP 数组 D 的每个元素 D[i][j] 表示 word1 的前 i 个字符和 word2 的前 j 个字符之间的最小编辑距离。
    初始化DP数组的边界条件:当 word2 为空时,word1 需要删除所有字符才能变为空串,所以 D[i][0] 被初始化为 i 。同理,D[0][j] 被初始化为 j

  3. 填充 DP 数组:
    对于D[i][j] ,有三种可能的操作:
    删除:将 word1 的第 i 个字符删除,此时 D[i][j] 依赖于 D[i-1][j],需要加1表示进行了一次删除操作。
    插入:在 word1 的前 i 个字符后插入 word2 的第 j 个字符,此时 D[i][j] 依赖于D[i][j-1],需要加1表示进行了一次插入操作。
    替换:如果word1的第i个字符和word2的第 j 个字符不同,则将word1的第i个字符替换为word2的第 j 个字符,此时D[i][j]依 赖于 D[i-1][j-1],需要加1表示进行了一次替换操作;如果两者相同,则不需要替换,D[i][j]就等于D[i-1][j-1]
    D[i][j]取上述三种操作中结果最小的那个。

GPT给出得已经较为完备,现在还没懂的原因就是,没有真正的去思考具体步骤。

去csdn找到一个比较清晰的版本,放下图,链接也放过来:详解编辑距离。

在这里插入图片描述
相关代码说明

// 删除操作int left = dp[i - 1][j] + 1;// 插入操作 int up = dp[i][j - 1] + 1;// 替换操作的基础值int left_up = dp[i - 1][j - 1];// 如果字符不同,需要替换,加1if(word1.charAt(i - 1) != word2.charAt(j - 1)){left_up += 1;}// 取三种操作中的最小值dp[i][j] = Math.min(left, Math.min(up, left_up));

那么我们以一个例子来说明具体过程:
如两个单词分别为 dog 和 doge。初始化行和列。

dog
0123
d1
o2
g3
e4

我们需要知道上的值
由于’d’ = ‘d’,两字符相等,我们取三的点最小值即为Math.min(1+1, Math.min( 1+1, 0+0))= 0

dog
0123
d10
o2
g3
e4

下面我们继续,向右遍历:‘d’ != ‘o’,Math.min(0+1, Math.min( 2+1, 1+1)) = 1

dog
0123
d101
o2
g3
e4

以此类推可以得到最终结果

dog
0123
d1012
o2101
g3210
e4321

下面代码演示

3、代码演示

public int minDistance(String word1, String word2) {// word1的长度和world2的长度 int n = word1.length();  int m = word2.length();// 如果有一个字符串为空,则编辑距离等于非空字符串的长度if(n * m == 0){return n + m ;}// 初始化DP数组,大小为(n+1) x (m+1)int [][] dp = new int [n + 1][m + 1];// 初始化DP数组的边界条件 // 当word2为空时,需要删除word1的所有字符for(int i = 0; i < n + 1; i++){dp[i][0] = i;}// 当word1为空时,需要插入word2的所有字符 for(int j = 0; j < m + 1; j++){dp[0][j] = j;}// 填充DP数组的其他元素for(int i = 1; i < n + 1; i++){for(int j = 1; j < m + 1; j++){// 删除操作int left = dp[i - 1][j] + 1;// 插入操作 int up = dp[i][j - 1] + 1;// 替换操作的基础值int left_up = dp[i - 1][j - 1];// 如果字符不同,需要替换,加1if(word1.charAt(i - 1) != word2.charAt(j - 1)){left_up += 1;}// 取三种操作中的最小值dp[i][j] = Math.min(left, Math.min(up, left_up));}}// 返回编辑距离return dp[n][m];        }

4、复杂度分析

  • 时间复杂度:O(mn),两个循环需要的时间,nworld1的长度,mworld2的长度。
  • 空间复杂度:O(mn),需要一个二维数组来保存中间值

5、总结

这题看着不简单,理解起来也确实不简单哈哈,不过最后还是理解了七七八八。Anyway,我要去吃午饭了,这道题做了好久,再见!

这篇关于LeetCode刷题之HOT100之编辑距离的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1042572

相关文章

LeetCode--231 2的幂

题目 给定一个整数,编写一个函数来判断它是否是 2 的幂次方。 示例 示例 1:输入: 1输出: true解释: 20 = 1示例 2:输入: 16输出: true解释: 24 = 16示例 3:输入: 218输出: false class Solution {public:bool isPowerOfTwo(int n) {if (n <= 0) return fals

LeetCode--234 回文链表

题目 请判断一个链表是否为回文链表。 示例 示例 1:输入: 1->2输出: false示例 2:输入: 1->2->2->1输出: true /*** Definition for singly-linked list.* struct ListNode {* int val;* ListNode *next;* ListNode(int x) : val

LeetCode--220 存在重复元素 III

题目 给定一个整数数组,判断数组中是否有两个不同的索引 i 和 j,使得 nums [i] 和 nums [j] 的差的绝对值最大为 t,并且 i 和 j 之间的差的绝对值最大为 ķ。 示例 示例 1:输入: nums = [1,2,3,1], k = 3, t = 0输出: true示例 2:输入: nums = [1,0,1,1], k = 1, t = 2输出: true示例

LeetCode--217 存在重复元素

题目 给定一个整数数组,判断是否存在重复元素。如果任何值在数组中出现至少两次,函数返回 true。如果数组中每个元素都不相同,则返回 false。 示例 示例 1:输入: [1,2,3,1]输出: true示例 2:输入: [1,2,3,4]输出: false示例 3:输入: [1,1,1,3,3,4,3,2,4,2]输出: true class Solution {p

LeetCode--214 最短回文串

题目 给定一个字符串 s,你可以通过在字符串前面添加字符将其转换为回文串。找到并返回可以用这种方式转换的最短回文串。 示例 示例 1:输入: "aacecaaa"输出: "aaacecaaa"示例 2:输入: "abcd"输出: "dcbabcd" 思路: 我们需要添加多少个字符与给定字符串的前缀子串回文的长度有关. 也就是说去掉其前缀的回文子串,我们只需要补充剩下的子串的逆序

LeetCode--206 反转链表

题目 反转一个单链表。 示例 示例:输入: 1->2->3->4->5->NULL输出: 5->4->3->2->1->NULL class Solution {public:ListNode* reverseList(ListNode* head) {if (head == nullptr || head->next == nullptr){return head;}ListNo

LeetCode--204 计数质数

题目 统计所有小于非负整数 n 的质数的数量。 示例 示例:输入: 10输出: 4解释: 小于 10 的质数一共有 4 个, 它们是 2, 3, 5, 7 。 class Solution {public:int countPrimes(int n) {if (n <= 2) return 0;int cnt = 0;vector<bool> isPrime(n, true);

LeetCode--198 打家劫舍

题目 你是一个专业的小偷,计划偷窃沿街的房屋。每间房内都藏有一定的现金,影响你偷窃的唯一制约因素就是相邻的房屋装有相互连通的防盗系统,如果两间相邻的房屋在同一晚上被小偷闯入,系统会自动报警。给定一个代表每个房屋存放金额的非负整数数组,计算你在不触动警报装置的情况下,能够偷窃到的最高金额。 示例 示例 1:输入: [1,2,3,1]输出: 4解释: 偷窃 1 号房屋 (金额 =

LeetCode--171 Excel表列序号

题目 给定一个Excel表格中的列名称,返回其相应的列序号。例如,A -> 1B -> 2C -> 3...Z -> 26AA -> 27AB -> 28 ... 示例 示例 1:输入: "A"输出: 1示例 2:输入: "AB"输出: 28示例 3:输入: "ZY"输出: 701 class Solution {public:int titleToNumber(strin

LeetCode--155 最小栈

题目 设计一个支持 push,pop,top 操作,并能在常数时间内检索到最小元素的栈。push(x) -- 将元素 x 推入栈中。pop() -- 删除栈顶的元素。top() -- 获取栈顶元素。getMin() -- 检索栈中的最小元素。 示例 MinStack minStack = new MinStack();minStack.push(-2);minStack.push