阿里巴巴笔试题 -- 动态规划实现两个字符串的最短编辑记录_最小编辑记录记录编辑过程

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

“ABC” --> “ABC” // 删除字符 B 即可


## 三、递归实现


### ♻️核心源码



package com.wanshi.test;

import org.junit.Test;

public class Test4 {

@Test
public void test() {
    String str1 = "ABC";
    String str2 = "BBC";
    long start = System.currentTimeMillis();
    int res = ld(str1, str2);
    long end = System.currentTimeMillis();
    System.out.println(res);
    System.out.println("运算时间:" + (end - start));
}

/\*\*

* 计算最短编辑距离
* @param str1 第一个字符串
* @param str2 第二个字符串
* @return 最短编辑距离次数
*/
private int ld(String str1, String str2) {
//如果内容相同了,直接返回即可,无操作
if (str1.equalsIgnoreCase(str2)) {
return 0;
}

    //如果第一个字符串是空,直接返回第二个字符串的长度,操作为插入第二个字符串的个数
    if (str1.equalsIgnoreCase("")) {
        return str2.length();
    }

    //如果第二个字符串是空,直接返回第一个字符串的长度,操作为插入第一个字符串的个数
    if (str2.equalsIgnoreCase("")) {
        return str1.length();
    }

    int ldRes = 0;

    //截取出两个字符串的第一个字符
    String str1Last = str1.substring(0, 1);
    String str2Last = str2.substring(0, 1);

    //截取后面的字符
    String str1Content = str1.substring(1);
    String str2Content = str2.substring(1);

    //如果相同就进入下一次计算
    if (str1Last.equalsIgnoreCase(str2Last)) {
        ldRes = ld(str1Content, str2Content);
    } else {

        //判断3次计算结果那次运算结果最少,就返回哪一个
        String strInsert = str1Last + str2;
        String strReplace = str1Last + str2Content;
        String strDel = str2Content;

        int ldInsert = ld(str1, strInsert);
        int ldReplace = ld(str1, strReplace);
        int ldDel = ld(str1, strDel);

        //获取三个操作中最短的编辑次数
        ldRes = Math.min(ldInsert, Math.min(ldReplace, ldDel)) + 1;
    }
    return ldRes;
}

}


### ⏰效果图


![在这里插入图片描述](https://img-blog.csdnimg.cn/4bab5f1fdd1b437a8445dfb60a73985d.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnIOe7iOe7k-iAhQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


### ⚠️递归实现的缺点


**我们把两个字符串换为以下字符**



String str1 = “最小编辑机双向停机短信提醒及距离是把一个字符串”;
String str2 = “关小编辑机双向停机短信提醒及优化出账时间的需求”;


**再次执行查看**


![在这里插入图片描述](https://img-blog.csdnimg.cn/d466a8f5c3554b8dbb6550d90c2df901.png?x-oss-process=image/watermark,type_d3F5LXplbmhlaQ,shadow_50,text_Q1NETiBAQnVnIOe7iOe7k-iAhQ==,size_20,color_FFFFFF,t_70,g_se,x_16#pic_center)


**跑到最后我笔记本风扇刷刷的!**


**不敢再跑下去了,`性能实在是太低了`!**


**我的笔记本 4+16的,速度算快的了,可还是因为在执行期间风扇一直转!**


`下面我们优化代码,这个代码必须优化,真的是性能太低太低!`


**为什么会这么慢呢?**



> 
> 第一我们的字符串太长,然后我们又是使用的**递归计算**,递归计算就是\*\*`一层一层往下走,然后一层一层往上返,执行步骤极多`**,导致一直出不来结果,所以需要**优化代码\*\*!
> 
> 
> 


## 四、递归+动态规划实现


动态规划最核心的思想,就在于**拆分子问题,记住过往,减少重复计算**。


**动态规划的好处就是:`可以大大提高系统的性能,使程序得到非常显著的性能提升!`**


### ♻️核心源码



package com.wanshi.test;

import org.junit.Test;

import java.util.HashMap;
import java.util.Map;

public class Test3 {

@Test
public void t1() {
    String str1 = "最小编辑机双向停机短信提醒及距离是把一个字符串";
    String str2 = "关小编辑机双向停机短信提醒及优化出账时间的需求";
    Map<String, Integer> ldMap = new HashMap<>();
    long start = System.currentTimeMillis();
    int res = ld(str1, str2, ldMap);
    long end = System.currentTimeMillis();
    System.out.println(res);
    System.out.println("运算时间:" + (end - start));
}

/\*\*

* 计算最短编辑距离
* @param str1 第一个字符串
* @param str2 第二个字符串
* @param ldMap map缓存
* @return 最短编辑距离次数
*/
private int ld(String str1, String str2, Map<String, Integer> ldMap) {
//如果内容相同了,直接返回即可,无操作
if (str1.equalsIgnoreCase(str2)) {
return 0;
}

    //如果第一个字符串是空,直接返回第二个字符串的长度,操作为插入第二个字符串的个数
    if (str1.equalsIgnoreCase("")) {
        return str2.length();
    }

    //如果第二个字符串是空,直接返回第一个字符串的长度,操作为插入第一个字符串的个数
    if (str2.equalsIgnoreCase("")) {
        return str1.length();
    }

    //键名
    String strKey = str1 + "\_" +str2;

    //如果map中存在该key,直接返回即可
    if (ldMap.containsKey(strKey)) {
        return ldMap.get(strKey);
    }
    int ldRes = 0;

    //截取出两个字符串的第一个字符
    String str1Last = str1.substring(0, 1);
    String str2Last = str2.substring(0, 1);

    //截取后面的字符
    String str12 = str1.substring(1);
    String str22 = str2.substring(1);

    //如果相同就进入下一次计算
    if (str1Last.equalsIgnoreCase(str2Last)) {
        ldRes = ld(str12, str22, ldMap);
    } else {
        //判断3次计算结果那次运算结果最少,就返回哪一个

img
img

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

oNTv-1715891484275)]

既有适合小白学习的零基础资料,也有适合3年以上经验的小伙伴深入学习提升的进阶课程,涵盖了95%以上C C++开发知识点,真正体系化!

由于文件比较多,这里只是将部分目录截图出来,全套包含大厂面经、学习笔记、源码讲义、实战项目、大纲路线、讲解视频,并且后续会持续更新

如果你需要这些资料,可以戳这里获取

  • 6
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值