• 返回将str1编辑成str2的最小代价


    问题描述:

            给定两个字符串str1和str2,再给定三个整数ic、dc和rc,分别代表插入、删 除和替换一个字符的代价,返回将str1编辑成str2的最小代价。

    【举例】
            str1="abc",str2="adc",ic=5,dc=3,rc=2 从"abc"编辑成"adc",把'b'替换成'd'是代价最小的,所以返回2
            str1="abc",str2="adc",ic=5,dc=3,rc=100 从"abc"编辑成"adc",先删除'b',然后插入'd'是代价最小的,所以返回8
            str1="abc",str2="abc",ic=5,dc=3,rc=2 不用编辑了,本来就是一样的字符串,所以返回0。

    思路

            动态规划的思想

            我们定义一个二维数组dp[N][M],N表示str1的长度+1,M表示str2的长度+1,二维数组dp[i][j]含义是str1到第i位置的字符串转化为str2到第j位置的字符串的最小代价。

            二维数组dp[i][j],dp[0][0] = 0,第一列的含义是str1转化为空的str2需要的最小代价即:dp[i][0] = dc * i。第一行的含义是空的str1转化为str2需要的最小代价即:dp[0][j] = ic * j 。

            按照str1转化为str2是否保存左后一个字符,分为两大类:

            1.保存str1最后一个字符,并且str2指针指向最后的位置。这一类根据str2中的最后一个字符是否的等于str1的最后字符又分为两小类。

                    1.1 相等:str1[i - 1] == str2[j - 1] 复制。        dp[i][j] = dp[i - 1][j - 1]

                    1.2 不相等:str1[i - 1] != str2[j - 1] 替换。        dp[i][j] =dp[i - 1][j - 1] + rc

            2.str1与str2的指针不同时指向最后的位置。

                    2.1 str1的指正指向最后位置,str2的指针指向倒数第二的位置。即str1从0 - i-1 转化为str2的0 - j-2 ,str2[j-1]最后插入:dp[i][j] =dp[i][j - 1] + ic。

                    2.2 str1的指正指向倒数第二的位置,str2的指针指向最后的位置。即str1从0 - i-2 转化为str2的0 - j-1 ,str1[i-1]最后删除:dp[i][j] =dp[i - 1][j] + dc。

            最后去这四种去请款的最小值存在dp[i][j]中。题目的最后结果存储在dp[N - 1][M - 1]中。

            同时我们也可以使用动态规划的空间压缩技术。

    代码

            动态规划

    1. public static int minCost1(String s1, String s2, int ic, int dc, int rc) {
    2. if (s1 == null || s2 == null) {
    3. return 0;
    4. }
    5. char[] str1 = s1.toCharArray();
    6. char[] str2 = s2.toCharArray();
    7. int N = str1.length + 1;
    8. int M = str2.length + 1;
    9. int[][] dp = new int[N][M];
    10. for (int i = 1; i < N; i++) {
    11. dp[i][0] = dc * i;
    12. }
    13. for (int j = 1; j < M; j++) {
    14. dp[0][j] = ic * j;
    15. }
    16. for (int i = 1; i < N; i++) {
    17. for (int j = 1; j < M; j++) {
    18. if (str1[i - 1] == str2[j - 1]) {
    19. dp[i][j] = dp[i - 1][j - 1];
    20. } else {
    21. dp[i][j] = dp[i - 1][j - 1] + rc;
    22. }
    23. dp[i][j] = Math.min(dp[i][j], dp[i][j - 1] + ic);
    24. dp[i][j] = Math.min(dp[i][j], dp[i - 1][j] + dc);
    25. }
    26. }
    27. return dp[N - 1][M - 1];
    28. }

            动态规划的空间压缩技术

    1. public static int minCost2(String s1, String s2, int ic, int dc, int rc) {
    2. if (s1 == null || s2 == null) {
    3. return 0;
    4. }
    5. char[] str1 = s1.toCharArray();
    6. char[] str2 = s2.toCharArray();
    7. char[] longs = str1.length >= str2.length ? str1 : str2;
    8. char[] shorts = str1.length < str2.length ? str1 : str2;
    9. if (str1.length < str2.length) {
    10. int tmp = ic;
    11. ic = dc;
    12. dc = tmp;
    13. }
    14. int[] dp = new int[shorts.length + 1];
    15. for (int i = 1; i <= shorts.length; i++) {
    16. dp[i] = ic * i;
    17. }
    18. for (int i = 1; i <= longs.length; i++) {
    19. int pre = dp[0];
    20. dp[0] = dc * i;
    21. for (int j = 1; j <= shorts.length; j++) {
    22. int tmp = dp[j];
    23. if (longs[i - 1] == shorts[j - 1]) {
    24. dp[j] = pre;
    25. } else {
    26. dp[j] = pre + rc;
    27. }
    28. dp[j] = Math.min(dp[j], dp[j - 1] + ic);
    29. dp[j] = Math.min(dp[j], tmp + dc);
    30. pre = tmp;
    31. }
    32. }
    33. return dp[shorts.length];
    34. }

  • 相关阅读:
    HTTP实现断点续传
    Spring Boot配置文件
    为什么说重写是运行时多态?
    ipv6地址概述——深入讲解ipv6地址
    Java 中是如何获取 IP 属地的
    解读数仓中的数据对象及相关关系
    【无标题】Java中的Optional
    3D孪生场景搭建:参数化模型
    Qt 二维码生成与识别
    antd的Table组件使用rowSelection属性实现多选时遇到的bug
  • 原文地址:https://blog.csdn.net/z1171127310/article/details/127812097