编辑距离| 豆包MarsCode AI刷题

49 阅读2分钟

问题描述

image.png

解题思路

这是一道相当经典的编辑距离题目,考察的就是对动态规划思维的运用以及对dp数组的定义,按照动态规划的老套路来做,首先第一步就是:

明确dp数组含义:

因为我们需要求得的是最少的编辑步骤,那么我们将这个当成数组的数值,那么因为需要进行比较,所以我们要有两个维度的参数来支撑,因此定义的就是一个二维数组,那么我们就可以明确dp数组是什么了:dp[i][j]表示第一个字符串前i个位置和第二个字符串前j个位置的最小编辑距离。

明确递推公式

我们对两个字符串进行比较时候,如果第i个位置等于第j个位置(的字符)那么就dp[i][j] = dp[i - 1][j - 1],但是如果不相等,这时候就需要分类讨论了,但是由于增加,删除,替换都是只进行一步操作,所以如果第i和第j个位置不相等的话,无非就是判断i和j-1是否相等,j和i-1是否相等,如果不等就是直接替换,体现到代码上面就比较简单,只需要判断大小,dp[i][j] = Math.min(dp[i - 1][j] + 1, Math.min(dp[i][j - 1] + 1, dp[i-1][j-1] + 1));

初始化

初始化是我们递推公式开始的第一步,一定要仔仔细细的查看,本题呢对dp数组进行理解,不难发现当有一个下标为零的时候,变换成它最少需要另外一个下标的数值(删除),由此我们就可以开始初始化。

遍历方向

遍历方向不是本题的难点,由递推公式就可以看出来,dp[i][j]依赖于前面的状态,所以遍历方向就是从前往后遍历。

public static int solution(String dna1, String dna2) {
        // Please write your code here
        int m = dna1.length();
        int n = dna2.length();
        int[][] dp = new int[m + 1][n + 1];
        // 初始化 dp 数组
        for (int i = 0; i <= m; i++) {
            dp[i][0] = i;
        }
        for (int j = 0; j <= n; j++) {
            dp[0][j] = j;
        }
        //dp数组的含义是第i个字符前(从零开始的)的编辑距离
        for(int i = 1; i <= m; i++){
            for( int j = 1; j <= n; j++){
                if(dna1.charAt(i -1 ) == dna2.charAt(j - 1)) dp[i][j] = dp[i - 1][j - 1];
                else{
                    dp[i][j] = Math.min(dp[i - 1][j] + 1, Math.min(dp[i][j - 1] + 1, dp[i-1][j-1] + 1));
                }
            }
        }
        return dp[m][n];
    }

总结

本题真的是相当经典编辑距离类题目,其代码值得好好琢磨,笔者认为,这里最主要的难点就是去判断这个递推公式,这是比较难想到的地方,但是如果你一下子就想到了这个逻辑判断,那么应该就会很快解决。