ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

LeetCode72、编辑距离(动态规划系列)

2021-03-05 21:59:16  阅读:178  来源: 互联网

标签:LeetCode72 系列 int length word1 word2 return 动态 dp


题目描述

https://leetcode-cn.com/problems/edit-distance/
在这里插入图片描述

解法

1、递归法(超时、备忘录通过)

  • 对于一些动态规划问题,我们思考时,我们不要去思考它是如何做使得现象发生的,我们只需要得到最终的结果即可。我们只关注于最值如何得到。
  • 我们还要思考递归函数,它对应的意义是什么?(对应上参数的意义)、
    比如这道题里面,minDp(i,j)表示字符串S1[0,i]变到S2[0,j]需要的最少步数。
class Solution {

    //使用递归,我们先来看如何计算

    //一般字符串的动态规划问题都是使用双指针,分别指向两个字符串的末尾,然后分别往前走,缩小问题的规模

    //
    private String word1;
    private String word2;
    public int minDistance(String word1, String word2) {
        if(word1==null) return word2.length();
        if(word2==null) return word1.length();
        this.word1 = word1;
        this.word2 = word2;
        return minDp(word1.length()-1,word2.length()-1);

    }
    public int minDp(int i,int j){
        if(i==-1 && j==-1) return 0;//两个指针同时到达边界
        if(i==-1||j==-1){//有一个指针先到达边界
            return j==-1?i+1:j+1;//直接添加或者删除剩余的部分
        }

        if(word1.charAt(i)==word2.charAt(j)){
            //相等,直接往前走
            return minDp(i-1,j-1);
        }else{
            //执行三种,替换dp(i-1,j-1)+1,删除dp(i-1,j)+1,插入 dp(i,j-1)+1
            return Math.min(
                Math.min(minDp(i-1,j-1)+1,minDp(i-1,j)+1)
                ,minDp(i,j-1)+1);
        }
    }
}

提交的时候,超时。

现在使用带备忘录的递归:

class Solution {

    //使用递归,我们先来看如何计算

    //一般字符串的动态规划问题都是使用双指针,分别指向两个字符串的末尾,然后分别往前走,缩小问题的规模

    //
    private String word1;
    private String word2;
    private int [][] dp;
    public int minDistance(String word1, String word2) {
        if(word1==null) return word2.length();
        if(word2==null) return word1.length();
        this.word1 = word1;
        this.word2 = word2;
        dp = new int[word1.length()][word2.length()];//用于备忘录
        return minDp(word1.length()-1,word2.length()-1);

    }
    public int minDp(int i,int j){
        if(i==-1 && j==-1) return 0;//两个指针同时到达边界
        if(i==-1||j==-1){//有一个指针先到达边界
            return j==-1?i+1:j+1;//直接添加或者删除剩余的部分
        }
        if(dp[i][j]!=0){
            return dp[i][j];//记录已经使用过的最少的数
        }

        if(word1.charAt(i)==word2.charAt(j)){
            //相等,直接往前走
            dp[i][j] = minDp(i-1,j-1);
        }else{
            //执行三种,替换dp(i-1,j-1)+1,删除dp(i-1,j)+1,插入 dp(i,j-1)+1
            dp[i][j] = Math.min(
                Math.min(minDp(i-1,j-1)+1,minDp(i-1,j)+1)
                ,minDp(i,j-1)+1);
        }
         return dp[i][j];
    }
}

在这里插入图片描述

2、使用迭代(动规)

动态递归需要思考如下问题:
(1) dp数组的维数和其意义——每个问题的阶段、状态
(2) dp数组的边界值
(3) dp数组如何进行遍历
(4) dp数组的递推是怎么个过程——上一阶段状态转换到下一阶段状态之间的递推关系.

很明显,因为我们要用到-1这个下标 ,但是因为数组下标从0开始,所以我们需要略作变化,让0表示原来的-1的意义。

1、dp[i+1][j+1]是二维数组,它的意义是S1[0,i]变为S2[0,j]的最少步数
2、边界情况:dp[0][0] = 0,此时的i=-1=j,步数为0;
	dp[0][j]=j,dp[i][0]=i,此时i=-1或j=-1,表示直接删除或者插入剩余的部分
3、dp数组的递推过程
	要用递归,当前要计算的dp(状态)使用已经算出来的dp(状态)
	if(s[i-1]==s[j-1]) dp[i][j] = dp[i-1][j-1]
	else dp[i][j] = min(dp[i-1][j]+1,dp[i][j-1]+1,dp[i][j-1]+1)

于是我们有:

class Solution {

    //使用递归,我们先来看如何计算

    //一般字符串的动态规划问题都是使用双指针,分别指向两个字符串的末尾,然后分别往前走,缩小问题的规模
    public int minDistance(String word1, String word2) {
        if(word1==null) return word2.length();
        if(word2==null) return word1.length();
        int [][] dp = new int[word1.length()+1][word2.length()+1];
        //边界
        for(int i=0;i<=word1.length();i++){
            dp[i][0] = i;
        }
        for(int i=0;i<=word2.length();i++){
            dp[0][i] = i;
        }
        for(int i=1;i<=word1.length();i++){
            for(int j=1;j<=word2.length();j++){
                if(word1.charAt(i-1)==word2.charAt(j-1)){//i实际对应下标s[i-1]
                //相等,直接往前走
                dp[i][j] = dp[i-1][j-1];
            }else{
                //执行三种,替换dp(i-1,j-1)+1,删除dp(i-1,j)+1,插入 dp(i,j-1)+1
                dp[i][j] = Math.min(
                    Math.min(dp[i-1][j-1]+1,dp[i-1][j]+1)
                    ,dp[i][j-1]+1);
            }
        }
    }
         return dp[word1.length()][word2.length()];
    }
}

在这里插入图片描述
看起来效率很低。

进行状态压缩(动态规划技巧,投影平面):
计算状态dp[i][j]需要的都是dp[i][j]相邻的状态,那么就可以使用状态压缩技巧,将二维的dp数组转化成一维,将空间复杂度从 O(N^2) 降低到 O(N)。

因为可读性很差,我也不太会。。就不做先了,会了再来。

标签:LeetCode72,系列,int,length,word1,word2,return,动态,dp
来源: https://blog.csdn.net/qq_44861675/article/details/114411735

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有