BM75 编辑距离(一)

描述

给定两个字符串 str1 和 str2 ,请你算出将 str1 转为 str2 的最少操作数。

你可以对字符串进行3种操作:

1.插入一个字符

2.删除一个字符

3.修改一个字符。

字符串长度满足 Java练习题—动态规划(十三)_Math ,保证字符串中只出现小写英文字母。

示例1

输入:

"nowcoder","new"
  • 1.

返回值:

6
  • 1.

说明:

"nowcoder"=>"newcoder"(将'o'替换为'e'),修改操作1次
"nowcoder"=>"new"(删除"coder"),删除操作5次
  • 1.
  • 2.


Java代码

import java.util.*;


public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     *
     * @param str1 string字符串
     * @param str2 string字符串
     * @return int整型
     */
    public int editDistance (String str1, String str2) {
        int s1Len = str1.length();
        int s2Len = str2.length();
        // 如果有一个字符串长度等于0,那么最小变换次数即为 s1Len + s2Len;
        if (s1Len == 0 || s2Len == 0) return s1Len + s2Len;


        // 初始化dp数组,dp[i][j] 记录 str1 每一个字符 变成 str2的次数
        int[][] dp = new int[s1Len + 1][s2Len +
                                        1]; // 第一行第一列,辅助单元格
        // 初始化第一行
        // 可以理解为: 将一个空串,转变为str2字符串从0 ~ i的字符 所需要的次数
        for (int i = 1; i < dp[0].length; i++) dp[0][i] = i;
        // 初始化第一列
        // 可以理解为: 将str1字符串从0 ~ i的字符 转变为 一个空串 所需要的次数
        for (int i = 1; i < dp.length; i++) dp[i][0] = i;

        // 下标从1开始遍历每一行
        for (int i = 1; i < dp.length; i++) {
            // 取出str1的 i索引字符
            char strChar1 = str1.charAt(i - 1);
            // 下标从1开始遍历每一列
            for (int j = 1; j < dp[0].length; j++) {
                // 取出str2的 j索引字符
                char strChar2 = str2.charAt(j - 1);
                // 如果相等,那么只需要取出左斜方单元格记录的次数即可
                if (strChar1 == strChar2) {
                    dp[i][j] = dp[i - 1][j - 1];
                } else {
                    // 如果不相等,取出左斜方,上方,左方的值,取最小后 + 1 即为当前 0 ~ i索引的str1字符串变换成 0 ~ j索引的str2字符串所需要的次数
                    int i1 = dp[i - 1][j - 1];
                    int i2 = dp[i][j - 1];
                    int i3 = dp[i - 1][j];
                    dp[i][j] = Math.min(i3, Math.min(i1, i2)) + 1;
                }
            }
        }

        // 循环结束,dp表格最后一个单元格记录的值,即为解
        return dp[s1Len][s2Len];
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.
  • 39.
  • 40.
  • 41.
  • 42.
  • 43.
  • 44.
  • 45.
  • 46.
  • 47.
  • 48.
  • 49.
  • 50.
  • 51.
  • 52.
  • 53.
  • 54.


import java.util.*;

public class Solution {
    int[][] memo; //备忘录,记录递归中间结果
    public int editDistance (String word1, String word2) {
        int len1 = word1.length();
        int len2 = word2.length();
        memo = new int[len1][len2];
        //初始化备忘录
        for (int[] row : memo) {
            Arrays.fill(row, -1);
        }
        //用二个指针从二个字符串末尾开始向前遍历
        return dp(word1, word2, len1- 1, len2 - 1);
    }
     //dp(i,j)表示以i的字符串s1变为以j结尾的s2的最少操作数
    int dp(String s1, String s2, int i, int j) {
        //如果s1遍历结束,则s1添加s2的剩余字符
        if (i == -1) return j + 1;
        //如果s2遍历结束,则s1删掉s2的剩余字符
        if (j == -1) return i + 1;

        //如果计算过则直接返回
        if (memo[i][j] != -1) {
            return memo[i][j];
        }
        //如果当前位置相等,则什么都不做
        if (s1.charAt(i) == s2.charAt(j)) {
            memo[i][j] = dp(s1, s2, i - 1, j - 1);
        } else { //如果不等,则进行增、删、换
            //增加:i比不变,j前移。删除:i前移,j不变
            int temp = Math.min(dp(s1, s2, i, j - 1), dp(s1, s2, i - 1, j)) + 1;
            //替换;i和j都前移
            memo[i][j] = Math.min(temp, dp(s1, s2, i - 1, j - 1) + 1);
        }
        return memo[i][j];
    }
}
  • 1.
  • 2.
  • 3.
  • 4.
  • 5.
  • 6.
  • 7.
  • 8.
  • 9.
  • 10.
  • 11.
  • 12.
  • 13.
  • 14.
  • 15.
  • 16.
  • 17.
  • 18.
  • 19.
  • 20.
  • 21.
  • 22.
  • 23.
  • 24.
  • 25.
  • 26.
  • 27.
  • 28.
  • 29.
  • 30.
  • 31.
  • 32.
  • 33.
  • 34.
  • 35.
  • 36.
  • 37.
  • 38.