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

简介: 阿里巴巴笔试题 -- 动态规划实现两个字符串的最短编辑记录
📢📢📢📣📣📣

哈喽!大家好,我是【 Bug 终结者】 ,【CSDN新星创作者】🏆,阿里云技术博主🏆,51CTO人气博主🏆,INfoQ写作专家🏆 <br/>
一位上进心十足,拥有极强学习力的【 Java领域博主】😜😜😜 <br/>
🏅【Bug 终结者】博客的领域是【面向后端技术】的学习,未来会持续更新更多的【后端技术】以及【学习心得】。 偶尔会分享些前端基础知识,会更新实战项目,面向企业级开发应用!
🏅 如果有对【后端技术】、【前端领域】感兴趣的【小可爱】,欢迎关注【Bug 终结者】💞💞💞


❤️❤️❤️ 感谢各位大可爱小可爱! ❤️❤️❤️

在这里插入图片描述

@TOC

一、题目说明

什么是最短编辑距离呢?假定有两个字符串s1和s2,允许对字符串进行以下三种操作:

  1. 插入一个字符
  2. 删除一个字符
  3. 替换一个字符

将字符串s1转换成字符串s2的最少操作次数就是字符串s1和字符串s2之间的最短编辑距离。两个字符串的最短编辑距离越短,意味着两个字符串越相似。

时间复杂度:O(m*n)

空间复杂度:O(m*n)

二、思路分析

下图为分析

在这里插入图片描述

上图可以看到,第一个字符串经过 新增、删除、修改后变为第二个字符串

例:

String str1 = "ABC";
String str2 = "BBC"
//我们经过以下操作将str1替换为str2

"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;
    }
}

⏰效果图

在这里插入图片描述

⚠️递归实现的缺点

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

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

再次执行查看

在这里插入图片描述

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

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

我的笔记本 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次计算结果那次运算结果最少,就返回哪一个
            int ldInsert = ld(str1, (str1Last + str2), ldMap);
            int ldReplace = ld(str1, (str1Last + str22), ldMap);
            int ldDel = ld(str1, str22, ldMap);

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

        }

        //存入map缓存,提高性能
        if (!ldMap.containsKey(strKey)) {
            ldMap.put(strKey, ldRes);
        }

        return ldRes;
    }

}

⏰效果图

在这里插入图片描述

✅递归+动态规划的好处

我们可以看到,只用递归实现跑这个跑的电脑差点爆炸,我们采用动态规划的方式优化代码后,性能瞬间就上来了,可见动态规划的好处!

提升了程序的性能,增加可用性,增强了程序的健壮性!

⛵小结

以上就是【Bug 终结者】对两个字符串的最短编辑记录简单的概述,本题为阿里巴巴笔试题,动态规划是常见的考题类型,所以说,大家要掌握好动态规划,合理的在系统中使用会极大的提高系统的性能!

如果这篇【文章】有帮助到你,希望可以给【 Bug 终结者】点个赞👍,创作不易,如果有对【 后端技术】、【 前端领域】感兴趣的小可爱,也欢迎关注❤️❤️❤️ 【 Bug 终结者】❤️❤️❤️,我将会给你带来巨大的【收获与惊喜】💝💝💝!
相关文章
|
域名解析 网络协议 安全
信息收集的工具你听过几种(盘点信息收集)
信息收集的工具你听过几种(盘点信息收集)
信息收集的工具你听过几种(盘点信息收集)
|
缓存 网络协议 Linux
解决github图片及网页加载不出来
解决github图片及网页加载不出来
1162 3
|
Python
pycharm正确配置国内镜像源的方式
配置国内镜像源和解决虚拟环境(Venv)中安装bs4或者其他的第三方库的错误 —— Could not find a version that satisfies the requirement bs4 国内镜像源推荐 阿里 mirrors.aliyun.com/pypi/simple… 清华 pypi.tuna.tsinghua.edu.cn/simple/ 豆瓣 pypi.douban.com/simple/ 注意这里都是 https 的,不然下载包的时候会出现其他
11591 0
|
6月前
|
人工智能 机器人 网络安全
使用 Lume 在 macOS 虚拟机中隔离运行 OpenClaw/Moltbot:完整部署指南
OpenClaw(龙虾)是开源本地AI智能体,可7×24小时在你设备上自主执行任务。支持微信/飞书/Telegram等50+渠道,具备持久记忆、网页浏览、文件操作与自我扩展能力,数据全留本地,隐私可控。(239字)
948 7
使用 Lume 在 macOS 虚拟机中隔离运行 OpenClaw/Moltbot:完整部署指南
|
人工智能 前端开发 API
如何快速开发视频下载器
本文介绍如何基于开源工具yt-dlp开发功能全面的视频下载器网站。yt-dlp作为youtube-dl的增强版,支持1000+网站,具备高效下载、格式选择及字幕处理等特性。文章详细解析了前后端架构设计,包括简洁的前端界面与基于Flask/Django的后端API实现,封装yt-dlp核心功能,提供进度跟踪和文件管理。同时探讨容器化部署、性能优化及扩展功能(如字幕翻译、批量下载)。案例“AI易视频”展示了AI辅助开发的高效性。开发时需遵守法律,尊重版权。
2707 11
|
存储 编译器 程序员
【C语言】auto 关键字详解
`auto` 关键字用于声明局部变量的自动存储类,其作用主要体现在变量的生命周期上。尽管现代C语言中 `auto` 的使用较少,理解其历史背景和作用对于掌握C语言的存储类及变量管理仍然很重要。局部变量默认即为 `auto` 类型,因此在实际编程中,通常不需要显式声明 `auto`。了解 `auto` 关键字有助于更好地理解C语言的存储类及其在不同场景中的应用。
1085 1
|
算法 物联网 数据库
阿里云 OpenSearch RAG 应用实践
本文介绍了阿里云OpenSearch在过去一年中在RAG方面的应用和探索。
29272 4
阿里云 OpenSearch RAG 应用实践
|
Ubuntu 虚拟化
Ubuntu安装VMtools实现与主机之间复制粘贴
一、安装 VMware Tools 右键点击你创建的系统,然后出现菜单下滑找到安装 VMware Tools(T) 这个点击安装; 右键点击你创建的系统,然后出现菜单下滑找到设置; 然后弹出虚拟机设置-->点击选项-->客户机隔离-->启用复制粘贴; 二、Ubuntu命令 这些命令假设你的Ubuntu系统已连接到互联网并且已配置为使用apt软件包管理器; 如果你的网络环境有限,你可能需要提前配置好网络或更换软件源; Ubuntu上安装和配置VMtools以实现与主机之间的文本复制粘贴功能; 1、打开终端(Terminal)。 2、运行以下命令以卸载旧版本的open-vm-tools: su
7289 1
|
前端开发 算法 测试技术
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
本文对比测试了通义千文、文心一言、智谱和讯飞等多个国产大模型在处理基础计数问题上的表现,特别是通过链式推理(COT)提示的效果。结果显示,GPTo1-mini、文心一言3.5和讯飞4.0Ultra在首轮测试中表现优秀,而其他模型在COT提示后也能显著提升正确率,唯有讯飞4.0-Lite表现不佳。测试强调了COT在提升模型逻辑推理能力中的重要性,并指出免费版本中智谱GLM较为可靠。
1279 0
前端大模型应用笔记(五):大模型基础能力大比拼-计数篇-通义千文 vs 文心一言 vs 智谱 vs 讯飞vsGPT
|
缓存 编译器 程序员
嵌入式开发环境Vscode开发STM32单片机程序
嵌入式开发环境Vscode开发STM32单片机程序
2324 1

热门文章

最新文章