当前位置: 首页 > article >正文

最短编辑距离问题与动态规划----LeetCode 72.编辑距离

动态规划(Dynamic Programming, DP)是解决复杂问题的一个强大工具,它将问题分解成更小的子问题,并使用这些子问题的解决方案来构建整体问题的解决方案。在深入探讨最短编辑距离问题之前,让我们先理解什么是动态规划,以及如何通过动态规划的视角来看待这个问题。

原题链接:72. 编辑距离 - 力扣(LeetCode)

动态规划分析

动态规划的核心

动态规划通常用于求解最优化问题。其核心思想包括两个主要部分:

  1. 最优子结构:问题的最优解包含其子问题的最优解。这意味着我们可以通过合并子问题的最优解来构造整个问题的最优解。

  2. 重叠子问题:在解决问题的过程中,问题被分解成若干个子问题,其中很多子问题是重复的。

最短编辑距离的动态规划解法

在最短编辑距离问题中,我们要将一个字符串word1转换成另一个字符串word2,并且我们希望所需的操作次数尽可能少。这里的操作包括插入、删除和替换字符。

集合定义

在这个问题中,我们定义f[i][j]word1的前i个字符转换到word2的前j个字符所需的最少操作次数。这个定义本身就隐含了一个最优子结构的性质,即要得到f[i][j]的值,我们可以依赖于f[i-1][j]f[i][j-1]f[i-1][j-1]的值,这些都是更小的子问题。

属性

在这个场景下,我们关注的属性是最小值(min),因为我们要找的是最少的操作次数。

转移方程

为了构建f[i][j],我们考虑以下三种可能的最后一步操作:

  • 插入:我们可以先将word1的前i个字符转换为word2的前j-1个字符,然后在末尾插入word2的第j个字符。这给我们 f[i][j-1] + 1 

  • 删除:我们可以先将word1的前i-1个字符转换为word2的前j个字符,然后删除word1的第i个字符。这给我们 f[i-1][j] + 1 

  • 替换或保持如果word1[i]word2[j]相同,我们不需要任何操作,只需要保持即可。如果它们不同,我们需要将word1[i]替换为word2[j],这给我们 f[i-1][j-1] + 1(如果不同)或f[i-1][j-1](如果相同)。

综上所述,转移方程可以表示为:

f[i][j] = min(      f[i][j - 1] + 1, 
                    f[i - 1][j] + 1, 
                    f[i - 1][j - 1] + (word1[i] != word2[j])
          );

其中,(word1[i]  !=  word2[j]) 是一个指示函数,word1[i]不等于word2[j]时值为1,否则为0。

实现

基于上述分析,我们可以实现动态规划解法来解决最短编辑距离问题。

class Solution {
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        int[][] f = new int[505][505];

        
        // 有一个字符串为空串
        if (n * m == 0) {
            return n + m;
        }

        for (int i = 1; i <= n; i++ ) {
            f[i][0] = i;
        }

        for (int i = 1; i <= m; i++ ) {
            f[0][i] = i;
        }

        for (int i = 1; i <= n; i++ ) {
            for (int j = 1; j <= m; j++ ) {
                f[i][j] = Math.min(f[i - 1][j] + 1, f[i][j - 1] + 1);
                f[i][j] = Math.min(f[i][j], f[i - 1][j - 1] + (word1.charAt(i - 1) == word2.charAt(j - 1) ? 0 : 1));
            }
        }
        return f[n][m];
    }
}

 

import java.util.*;

public class Main{
    public static void main(String[] args) {
        Scanner sca = new Scanner(System.in);
        int N = 1010; // 假设字符串的最大长度
        char[] a = new char[N];
        char[] b = new char[N];
        int[][] f = new int[N][N]; // 动态规划数组

        int n = sca.nextInt(); // word1的长度
        String A = sca.next(); // word1
        int m = sca.nextInt(); // word2的长度
        String B = sca.next(); // word2

        // 初始化边界条件
        for (int i = 1; i <= n; i++ ) {
            a[i] = A.charAt(i - 1);
            f[i][0] = i;
        }
        for (int i = 1; i <= m; i++ ) {
            b[i] = B.charAt(i - 1);
            f[0][i] = i;
        }

        // 动态规划填表
        for (int i = 1; i <= n; i++ ) {
            for (int j = 1; j <= m; j++ ) {
                f[i][j] = Math.min(f[i][j - 1] + 1, f[i - 1][j] + 1);
                if (a[i] == b[j]) f[i][j] = Math.min(f[i][j], f[i - 1][j - 1]);
                else f[i][j] = Math.min(f[i][j], f[i - 1][j - 1] + 1);
            }
        }

        System.out.println(f[n][m]); // 输出结果
    }
}

时间复杂度

这个解法的时间复杂度为O(nm),其中nm分别是字符串word1word2的长度。这是因为我们需要填充一个n x m的二维数组。


http://www.kler.cn/a/228610.html

相关文章:

  • Linux底层基础知识
  • 回归预测 | Matlab实现WOA-CNN-LSTM-Attention鲸鱼算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)
  • Go语言学习踩坑记
  • golang开发window环境搭建
  • 【工具】使用asciidoctor-pdf将adoc文件转换成pdf
  • 回归预测 | Matlab实现OOA-CNN-LSTM-Attention鱼鹰算法优化卷积长短期记忆网络注意力多变量回归预测(SE注意力机制)
  • 5G智能卷烟工厂数字孪生可视化平台,推进烟草行业数字化转型
  • 贪心算法篇
  • 属性“xxxx”在类型“ArrayConstructor”上不存在。是否需要更改目标库? 请尝试将 “lib” 编译器选项更改为“es2015”或更高版本。
  • PMP资料怎么学?PMP备考经验分享
  • uniapp android和微信小程序实现PDF在线预览
  • Java环境配置
  • redis下载与安装教程(centos下)
  • 外汇天眼:黑平台CCF Markets专坑华人,交钱才能出金!
  • Facebook的数字合作愿景:创新与未来发展
  • kubekey网页版安装k8s集群操作流程
  • 【百度Apollo】自动驾驶规划技术:实现安全高效的智能驾驶
  • C语言常见面试题:C语言中如何进行视频处理编程?
  • Swift Vapor 教程(查询数据、插入数据)
  • LabVIEW智能温度直流模件自动测试系统