leetcode583. 两个字符串的删除操作(java-动态规划)

265 篇文章 2 订阅
235 篇文章 0 订阅

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

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

题目描述

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

示例 1:
输入: word1 = “sea”, word2 = “eat”
输出: 2
解释: 第一步将 “sea” 变为 “ea” ,第二步将 "eat "变为 “ea”

示例 2:
输入:word1 = “leetcode”, word2 = “etco”
输出:4

提示:
1 <= word1.length, word2.length <= 500
word1 和 word2 只包含小写英文字母

解题思路

这题最直观的思考还是暴力递归,用两个指针,卡住两个单词的起始位置,如果相同,同时跳到下一个位置,如果不同,就有两种情况了,是单词1删除还是单词2删除,因为要求出最小步数,所以,我们要两种情况都去考虑,要最小值.

解法一 递归加缓存

  /**
     * 最小步数
     * @param word1
     * @param word2
     * @return
     */
    public int minDistance(String word1, String word2) {
        int n = word1.length();
        int m = word2.length();
        int[][] dp = new int[n + 1][m + 1];
        return process(word1.toCharArray(),n - 1,word2.toCharArray(),m - 1,dp);
    }

    /**
     * 暴力递归加缓存 
     * @param word1
     * @param i 
     * @param word2
     * @param j
     * @param dp
     * @return
     */
    public int process(char[] word1,int i,char[] word2,int j,int[][]dp){
        if (i == -1 && j == -1){
            return 0;
        }
        if (i == -1){
            return j + 1;
        }
        if (j == -1){
            return i + 1;
        }
        if (dp[i][j] != 0){
            return dp[i][j];
        }
        int res = 0;
        //相等时,当前不做操作,等于下一个位置,
        if(word1[i] == word2[j]){
            res = process(word1,i - 1,word2, j - 1,dp);
        }else{
            //word1 删除
            int p1 = process(word1,i -  1,word2,j ,dp);
            //word2 删除
            int p2 = process(word1,i ,word2,j - 1,dp);
            //取两种情况最小步数,加上当前字符本身操作,
            res = Math.min(p1,p2) + 1;
        }
        dp[i][j] = res;
        return res;
    }

动态规划

暴力递归改动态规划,分为三个步骤,
1.初始化dp表
2.把递归过程改成从表中拿值的过程
3.返回dp表数据

先看下如何初始化,如果word1 长度为0 时,那么操作的次数就是把word2 全部删除,就是word2 的长度,反之,word2 长度是0 的时候,需要操作的步数就是word1 的长度,由此我们可以初始化出表中的数据,
如图演示:
在这里插入图片描述
第一行和第一列就可以初始出来了,
操作时,从1开始,比较时别忘记减1.

代码演示

  /**
     * 动态规划
     * @param word1
     * @param word2
     * @return
     */
    public int minDistance(String word1, String word2){
        int n = word1.length();
        int m = word2.length();
        int[][] dp = new int[n + 1][m + 1];
        //第一行
        for (int i = 1;i <= m;i++){
            dp[0][i] = i;
        }
        //第一列
        for (int j = 1; j <= n;j++){
            dp[j][0] = j;
        }
        for (int i = 1; i <= n;i++){
            for (int j = 1; j <= m;j++){
                //比较时,要减1,下标从0开始的
                if (word1.charAt(i - 1) == word2.charAt(j - 1)){
                    dp[i][j] = dp[i - 1][j - 1];
                }else{
                    int p1 = dp[i - 1][j];
                    int p2 = dp[i][j - 1];
                    dp[i][j] = Math.min(p1,p2) + 1;
                }
            }
        }
        return dp[n][m];
    }

动态规划专题

leetcode514. 自由之路

leetcode887. 鸡蛋掉落

leetcode1884. 鸡蛋掉落-两枚鸡蛋

leetcode312. 戳气球

leetcode787. K 站中转内最便宜的航班

leetcode62. 不同路径

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值