首页
技术小册
AIGC
面试刷题
技术文章
MAGENTO
云计算
视频课程
源码下载
PDF书籍
「涨薪秘籍」
登录
注册
01 | 合格程序员的第一步:算法与数据结构
02 | 如何事半功倍地学习算法与数据结构
03 | 如何计算算法的复杂度
04 | 如何通过LeetCode来进行算法题目练习
05 | 理论讲解:数组&链表
06 | 面试题:反转一个单链表&判断链表是否有环
07 | 理论讲解:堆栈&队列
08 | 面试题:判断括号字符串是否有效
09 | 面试题:用队列实现栈&用栈实现队列
10 | 理论讲解:优先队列
11 | 面试题:返回数据流中的第K大元素
12 | 面试题:返回滑动窗口中的最大值
13 | 理论讲解:哈希表
14 | 面试题:有效的字母异位词
15 | 面试题:两数之和
16 | 面试题:三数之和
17 | 理论讲解:树&二叉树&二叉搜索树
18 | 面试题:验证二叉搜索树
19 | 面试题:二叉树&二叉搜索树的最近公共祖先
20 | 理论讲解:二叉树遍历
21 | 理论讲解:递归&分治
22 | 面试题:Pow(x,n)
23 | 面试题:求众数
24 | 理论讲解:贪心算法
25 | 面试题:买卖股票的最佳时机
26 | 理论讲解:广度优先搜索
27 | 理论讲解:深度优先搜索
28 | 面试题:二叉树层次遍历
29 | 面试题:二叉树的最大和最小深度
30 | 面试题:生成有效括号组合
31 | 理论讲解:剪枝
32 | 面试题:N皇后问题
33 | 面试题:数独问题
34 | 理论讲解:二分查找
35 | 面试题:实现一个求解平方根的函数
36 | 理论讲解:字典树
37 | 面试题:实现一个字典树
38 | 面试题:二维网格中的单词搜索问题
39 | 理论讲解:位运算
40 | 面试题:统计位1的个数
41 | 面试题:2的幂次方问题&比特位计数问题
42 | 面试题:N皇后问题的另一种解法
43 | 理论理解:动态规划(上)
44 | 理论理解:动态规划(下)
45 | 面试题:爬楼梯
46 | 面试题:三角形的最小路径和
47 | 面试题:乘积最大子序列
48 | 面试题:股票买卖系列
49 | 面试题:最长上升子序列
50 | 面试题:零钱兑换
51 | 面试题:编辑距离
52 | 理论讲解:并查集
53 | 面试题:岛屿的个数&朋友圈(上)
54 | 面试题:岛屿的个数&朋友圈(下)
55 | 理论讲解: LRU Cache
56 | 面试题:设计和实现一个LRU Cache缓存机制
57 | 理论讲解:布隆过滤器
当前位置:
首页>>
技术小册>>
算法面试通关 50 讲
小册名称:算法面试通关 50 讲
### 51 | 面试题:编辑距离 #### 引言 在算法面试的浩瀚星空中,“编辑距离”(Edit Distance)问题犹如一颗璀璨的星辰,以其深刻的数学背景和广泛的应用领域,成为了众多面试官青睐的考题之一。编辑距离,又称莱文斯坦距离(Levenshtein Distance),衡量的是将一个字符串转换成另一个字符串所需的最少编辑操作次数,这些编辑操作包括插入、删除和替换字符。它不仅在文本处理、生物信息学、拼写检查等领域有重要应用,也是评估字符串相似度的一种有效手段。 #### 问题定义 给定两个字符串`s1`和`s2`,要求计算它们之间的编辑距离。编辑距离定义为将`s1`转换为`s2`所需的最少单字符编辑(插入、删除或替换)次数。 #### 解决方案概述 解决编辑距离问题最经典且高效的方法是使用动态规划(Dynamic Programming, DP)。动态规划通过将原问题拆解为规模较小的子问题,并存储子问题的解来避免重复计算,从而优化整体性能。 #### 动态规划解法 ##### 1. 定义状态 设`dp[i][j]`表示将`s1`的前`i`个字符转换为`s2`的前`j`个字符所需的最少编辑次数。注意,这里的“前`i`个字符”和“前`j`个字符”是包含索引`i-1`和`j-1`的字符在内的子串。 ##### 2. 初始化 - 当`i=0`时,即`s1`为空字符串,要将空字符串转换成`s2`的前`j`个字符,只能通过`j`次插入操作,因此`dp[0][j] = j`。 - 同理,当`j=0`时,`dp[i][0] = i`,即将`s1`的前`i`个字符转换为空字符串,需要`i`次删除操作。 ##### 3. 状态转移方程 对于`i > 0`且`j > 0`的情况,我们需要考虑三种操作: - **替换**:如果`s1[i-1] == s2[j-1]`,则当前字符无需编辑,直接继承前一个状态的结果,即`dp[i][j] = dp[i-1][j-1]`。 - **插入**:在`s1`的第`i`个位置插入一个与`s2[j-1]`相同的字符,相当于将`s1`的前`i-1`个字符转换为`s2`的前`j`个字符,然后再添加一个字符(即插入操作),所以`dp[i][j] = dp[i-1][j] + 1`。 - **删除**:删除`s1`的第`i`个字符,相当于将`s1`的前`i-1`个字符转换为`s2`的前`j`个字符,因此`dp[i][j] = dp[i][j-1] + 1`。 综合以上三种情况,取最小值作为`dp[i][j]`的值,即: \[ dp[i][j] = \min(dp[i-1][j-1] + (s1[i-1] \neq s2[j-1]), dp[i-1][j] + 1, dp[i][j-1] + 1) \] ##### 4. 填表过程 按照上述状态转移方程,从`dp[0][0]`开始,逐步填充整个`dp`表,直到`dp[m][n]`,其中`m`和`n`分别是`s1`和`s2`的长度。 ##### 5. 返回结果 最终,`dp[m][n]`即为所求的编辑距离。 #### 代码实现(Python) ```python def minDistance(s1, s2): m, n = len(s1), len(s2) dp = [[0] * (n + 1) for _ in range(m + 1)] # 初始化 for i in range(m + 1): dp[i][0] = i for j in range(n + 1): dp[0][j] = j # 填表 for i in range(1, m + 1): for j in range(1, n + 1): if s1[i - 1] == s2[j - 1]: cost = 0 else: cost = 1 dp[i][j] = min(dp[i - 1][j - 1] + cost, dp[i - 1][j] + 1, dp[i][j - 1] + 1) return dp[m][n] # 示例 s1 = "kitten" s2 = "sitting" print(minDistance(s1, s2)) # 输出: 3 ``` #### 复杂度分析 - **时间复杂度**:O(m * n),其中m和n分别是两个字符串的长度。因为需要填充一个m+1行n+1列的二维数组。 - **空间复杂度**:O(m * n),同样是由于需要存储m+1行n+1列的二维数组。 #### 优化空间复杂度 虽然上述解法在时间和空间上都是高效的,但有时候面试中可能会要求进一步优化空间复杂度。观察状态转移方程,我们可以发现`dp[i][j]`只依赖于其左边、上边和左上方的值,因此可以使用滚动数组或一维数组来优化空间复杂度至O(n)。 #### 应用场景 编辑距离在多个领域都有广泛的应用,包括但不限于: - **拼写检查**:在自动拼写检查系统中,编辑距离可以帮助识别并纠正打字错误。 - **生物信息学**:在DNA序列分析中,编辑距离用于衡量不同物种间的基因序列差异。 - **数据清洗**:在数据预处理阶段,编辑距离可以用来识别并修正数据集中的不一致性。 #### 结语 编辑距离问题不仅考察了面试者对动态规划算法的理解和掌握程度,还考验了其对问题建模和优化的能力。通过深入理解编辑距离的原理和实现细节,我们可以更好地应对面试中的类似问题,并在实际项目中灵活运用这一强大的工具。
上一篇:
50 | 面试题:零钱兑换
下一篇:
52 | 理论讲解:并查集
该分类下的相关小册推荐:
编程之道-算法面试(下)
数据结构与算法之美
业务开发实用算法精讲
编程之道-算法面试(上)
数据结构与算法(中)
数据结构与算法(下)
数据结构与算法(上)