刷题66(力扣3道题-动态规划)

103.编辑距离

题目链接

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/edit-distance

题目描述

给你两个单词 word1 和 word2,请你计算出将 word1 转换成 word2 所使用的最少操作数 。

你可以对一个单词进行如下三种操作:

插入一个字符
删除一个字符
替换一个字符
 

示例 1:

输入:word1 = "horse", word2 = "ros"
输出:3
解释:
horse -> rorse (将 'h' 替换为 'r')
rorse -> rose (删除 'r')
rose -> ros (删除 'e')
示例 2:

输入:word1 = "intention", word2 = "execution"
输出:5
解释:
intention -> inention (删除 't')
inention -> enention (将 'i' 替换为 'e')
enention -> exention (将 'n' 替换为 'x')
exention -> exection (将 'n' 替换为 'c')
exection -> execution (插入 'u')

重难点

  1. 动态规划
  2. 状态转移方程

题目分析

  1. 定义二维数组并初始化;
  2. dp[i][j]表示:word1的前i个字母要转成word2的前j个字母所需的最小操作数;
  3. dp状态转移方程:若word1[i-1] == word2[j-1] ,dp状态转移方程:dp[i-1][j-1];若word1[i-1] != word2[j-1] ,dp状态转移方程:Math.min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1]) + 1,其中:dp[i-1][j] 表示删除操作,dp[i][j-1] 表示插入操作,dp[i-1][j-1] 表示替换操作;
  4. 如果i*j==0,即有一个单词为0,直接返回i+j;

/**
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
var minDistance = function(word1, word2) {
    let n = word1.length;
    let m = word2.length;
    let dp = [];
    for(let i=0;i<=n;i++){
        dp.push([]);
        for(let j=0;j<=m;j++){
            if(i * j){
                dp[i][j] = word1[i-1] == word2[j-1] ? dp[i-1][j-1] : (Math.min(dp[i-1][j],dp[i][j-1],dp[i-1][j-1])+1);
            }else{
                dp[i][j] = i+j;
            }
        }
    }
    return dp[n][m];
};

104.两个字符串的删除操作

题目链接

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/delete-operation-for-two-strings

题目描述

给定两个单词 word1 和 word2,找到使得 word1 和 word2 相同所需的最小步数,每步可以删除任意一个字符串中的一个字符。

示例:

输入: "sea", "eat"
输出: 2
解释: 第一步将"sea"变为"ea",第二步将"eat"变为"ea"
 

提示:

给定单词的长度不超过500。
给定单词中的字符只含有小写字母。

重难点

  1. 动态规划
  2. 状态转移方程

题目分析

  1. 定义二维数组并初始化;
  2. dp[i][j]表示:找到word1的前i个字母和word2的前j个字母相同的最小步数;
  3. dp状态转移方程:若word1[i-1] == word2[j-1] ,dp状态转移方程:dp[i-1][j-1];若word1[i-1] != word2[j-1] ,dp状态转移方程:Math.min(dp[i-1][j],dp[i][j-1]) + 1;
  4. 如果i*j==0,即有一个单词为0,直接返回i+j;

/**
 * @param {string} word1
 * @param {string} word2
 * @return {number}
 */
var minDistance = function(word1, word2) {
    let n = word1.length;
    let m = word2.length;
    let dp = [];
    for(let i=0;i<=n;i++){
        dp.push([]);
        for(let j=0;j<=m;j++){
            if(i * j){
                dp[i][j] = word1[i-1] == word2[j-1] ? dp[i-1][j-1] : (Math.min(dp[i-1][j],dp[i][j-1])+1);
            }else{
                dp[i][j] = i+j;
            }
        }
    }
    return dp[n][m];
};

105.不相交的线

题目链接

来源:力扣(LeetCode)
链接:https://leetcode-cn.com/problems/uncrossed-lines

题目描述

我们在两条独立的水平线上按给定的顺序写下 A 和 B 中的整数。

现在,我们可以绘制一些连接两个数字 A[i] 和 B[j] 的直线,只要 A[i] == B[j],且我们绘制的直线不与任何其他连线(非水平线)相交。

以这种方法绘制线条,并返回我们可以绘制的最大连线数。

示例 1:

输入:A = [1,4,2], B = [1,2,4]
输出:2
解释:
我们可以画出两条不交叉的线,如上图所示。
我们无法画出第三条不相交的直线,因为从 A[1]=4 到 B[2]=4 的直线将与从 A[2]=2 到 B[1]=2 的直线相交。
示例 2:

输入:A = [2,5,1,2,5], B = [10,5,2,1,5,2]
输出:3
示例 3:

输入:A = [1,3,7,1,7,5], B = [1,9,2,5,1]
输出:2
 

提示:

1 <= A.length <= 500
1 <= B.length <= 500
1 <= A[i], B[i] <= 2000

重难点

  1. 动态规划
  2. 状态转移方程

题目分析

  1. 定义二维数组并初始化;
  2. dp[i][j]表示:A的前i条线要连接B的前j条线最大的不相交连接数;
  3. 如果i*j!=0,两组线都存在,计算dp状态转移方程;
  4. dp状态转移方程:若A[i-1] == B[j-1] ,dp状态转移方程:dp[i-1][j-1]+1;若A[i-1] != B[j-1] ,dp状态转移方程:Math.min(dp[i-1][j],dp[i][j-1])。
/**
 * @param {number[]} A
 * @param {number[]} B
 * @return {number}
 */
var maxUncrossedLines = function(A, B) {
    let n = A.length;
    let m = B.length;
    let dp = [];
    for(let i=0;i<=n;i++){
        dp[i] = new Array();
        for(let j=0;j<=m;j++){
            dp[i][j] = 0;
        }
    }
    for(let i=0;i<=n;i++){
        for(let j=0;j<=m;j++){
            if(i * j){
                dp[i][j] = A[i-1] == B[j-1] ? dp[i-1][j-1]+1 : Math.max(dp[i-1][j],dp[i][j-1]);
             }
        }
    }
    return dp[n][m];
};

  

原文地址:https://www.cnblogs.com/liu-xin1995/p/12642688.html