【算法】【字符串模块】字符串数组中两个字符之间的最短距离以及对hashcode以及equals的理解

news2025/2/2 10:46:52

目录

  • 前言
  • 问题介绍
  • 解决方案
  • 代码编写
    • java语言版本
    • c语言版本
    • c++语言版本
  • 思考感悟
  • 写在最后

前言

当前所有算法都使用测试用例运行过,但是不保证100%的测试用例,如果存在问题务必联系批评指正~

在此感谢左大神让我对算法有了新的感悟认识!

问题介绍

原问题
给定字符串chars,两个字符char1,char2,求在chars中,char1和char2之间的最短距离
如:
chars = [1,3,3,3,2,3,1], char1 = 1, char2 = 2
结果为:2
进阶问题
在原问题的基础上,牺牲空间复杂度,换取时间复杂度,并且能够做到任何char1和char2之间的最短距离获取复杂度为O(1)

解决方案

原问题
1、首先申请两个变量index1,index2。index1代表最近一次找到char1的index,index2代表最近一次找到char2的index
2、每一次找到char1和char2时更新index1和index2,然后计算一次index1和index2之间的距离,找到最小值即可。
进阶问题
1、申请一个map,key为Char类型,value为Map类型,value的mapkey为char类型,value为Integer类型,即Map<Character,Map<Character,Integer >
2、遍历chars,每新增一个chars[i]时,更新char[0… i]的所有key,重新计算与chars[i]之间的距离
空间复杂度:O(n^2) ,查询时间复杂度O(1)

代码编写

java语言版本

原问题:

   /**
     * 二轮测试:问题一
     * @return
     */
    public static int minDisCp1(char[] chars, char c1, char c2) {
        if (chars == null || chars.length == 0) {
            return -1;
        }
        if (c1 == c2) {
            return 0;
        }
        // c1 最近出现的位置
        int last1 = -1;
        // c2 最近出现的位置
        int last2 = -1;
        int min = Integer.MAX_VALUE;
        for (int i = 0; i < chars.length; i++) {
            if (chars[i] != c1 && chars[i] != c2) {
                continue;
            }
            if (chars[i] == c1) {
                last1 = i;
                if (last2 != -1) {
                    min = Math.min(min,i - last2);
                }
            }
            if (chars[i] == c2) {
                last2 = i;
                if (last1 != -1) {
                    min = Math.min(min, i - last1);
                }
            }
        }
        return min == Integer.MAX_VALUE ? -1 : min;
    }

进阶问题

    public static void main(String[] args) {
        //System.out.println(minDisCp1(new char[]{'1', '3', '3', '3', '2', '3', '1'}, '1', '2'));
        MinDistanceCp2 minDistanceCp2 = new MinDistanceCp2(new char[]{'1', '3', '3', '3', '2', '3', '1'});
        minDistanceCp2.getMinDis('1', '2');
    }


    /**
     * 进阶问题使用工具类实现
     */
    public static class MinDistanceCp2{
        private Map<Character, Map<Character, Integer>> map;

        public MinDistanceCp2(char[] chars) {
            this.map = new HashMap<>();
            init(chars);
        }

        /**
         * 初始化统计最短距离填充map
         * @param chars
         */
        private void init(char[] chars) {
            if (chars == null || chars.length == 0) {
                return;
            }
            for (int i = 0; i < chars.length; i++) {
                if (!map.containsKey(chars[i])) {
                    map.put(chars[i], new HashMap<>());
                    // 距离自己是0
                    map.get(chars[i]).put(chars[i], 0);
                }
                dealChar(chars, i);
            }
        }

        /**
         * 遍历所有数组,更新最近距离
         * @param index
         * @Param chars
         */
        private void dealChar(char[] chars, int index) {
            for (int i = 0; i < index; i++) {
                int dis = index - i;
                Map<Character, Integer> mapI = this.map.get(chars[i]);
                Map<Character, Integer> mapIndex = this.map.get(chars[index]);
                // 更新i处的
                if (mapI.get(chars[index]) == null || mapI.get(chars[index]) > dis) {
                    mapI.put(chars[index], dis);
                }
                // 更新index
                if (mapIndex.get(chars[i]) == null || mapIndex.get(chars[i]) > dis) {
                    mapIndex.put(chars[i], dis);
                }
            }
        }

        /**
         * 获取最短距离
         * @param c1
         * @param c2
         * @return
         */
        private int getMinDis(char c1, char c2) {
            if (map.get(c1) == null || map.get(c2) == null) {
                return 0;
            }
            return map.get(c1).get(c2) == null ? -1 : map.get(c1).get(c2);
        }
    }

c语言版本

正在学习中

c++语言版本

正在学习中

思考感悟

这道题表面上是计算字符串中的最短距离,实际上可以抽象到工具类,字符可以变为泛型,我们可以使用这个思想计算任何对象数组中两个对象之间的最短距离,业务也会有此需求的。
还有一点需要注意的就是,这里HashMap对于8大基本变量由于jvm常量池和装箱拆箱的操作,我们可以直接对常量进行put,而使用对象作为key的时候,可能会出现你认为相等的两个对象(值相等)但是却能够同时存在于map中作为两个key存在。原因是因为hashmap判断key是否相等的逻辑是:
1、首先通过hash值(这里hash不是hashcode,是高16位和低16位的异或结果)找到Node列表tab的坐标,也就是数组中的头结点,如果p为null,则直接630行,表示该桶是空桶。
2、如果不为null说明该桶有值了,这个时候判断key存在的逻辑在633和634行,说明先比较hash相等(冲突)并且Node对象中的key地址相等或者equals为true(可以重写)时两个对象相等。
在这里插入图片描述
因此如果我们使用对象作为key,不同的对象,但是值相同,需要重写equals和hashcode,必须重写hashcode才能通过633行的判断,这也就是为什么面试中经常问到的一个问题:equals重写,hashcode为什么一定要重写?

后面会有一篇关于java基本数据结构的源码解读,欢迎大家前来指导~

写在最后

方案和代码仅提供学习和思考使用,切勿随意滥用!如有错误和不合理的地方,务必批评指正~
如果需要git源码可邮件给2260755767@qq.com
再次感谢左大神对我算法的指点迷津!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/104103.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

来聊一聊|ConcurrentModificationException异常的解决

一. 前言 最近耀哥的一个学生&#xff0c;在使用使用ArrayList的subList的时候&#xff0c;发生了ConcurrentModificationException的异常。耀哥觉得这个现象非常具有代表性&#xff0c;估计有不少同学都会在同样的问题上犯迷糊&#xff0c;所以今天耀哥特意把这个问题记录下来…

设备台账管理系统

开发工具(eclipse/idea/vscode等)&#xff1a; 数据库(sqlite/mysql/sqlserver等)&#xff1a; 功能模块(请用文字描述&#xff0c;至少200字)&#xff1a; 模块划分&#xff1a;公告类型、公告信息、员工信息、仓库信息、设备类型、设备信息、供应商信息、采购信息、设备调拨、…

8个Spring事务失效的场景,你碰到过几种?

前言 作为Java开发工程师&#xff0c;相信大家对Spring种事务的使用并不陌生。但是你可能只是停留在基础的使用层面上&#xff0c;在遇到一些比较特殊的场景&#xff0c;事务可能没有生效&#xff0c;直接在生产上暴露了&#xff0c;这可能就会导致比较严重的生产事故。今天&a…

基于Android7 的msm8953芯片的nfc调试

目录 报错日志 NFC芯片重要的5个引脚 时序图分析 报错日志 01-01 19:05:22.570 0000 2341 2532 D NxpFwDnld: phDnldNfc_InitImgInfo:SUCCESS 01-01 19:05:22.570 0000 2341 2532 D NxpFwDnld: Processing Normal Sequence.. 01-01 19:05:22.570 0000 2341 2532 D NxpFwD…

干货|PCB电路板的组成、设计、工艺、流程及元器摆放和布线原则

大家对PCB电路板电路这个词很熟&#xff0c;有的了解PCB电路板的组成&#xff0c;有的了解PCB电路板的设计步骤&#xff0c;有的了解PCB电路板的制作工艺......但是对整个PCB电路板的组成、设计、工艺、流程及元器摆放和布线原则&#xff0c;及后期的注意事项没有一个综合的了解…

Spring 中 ConfigurationClassPostProcessor 类扫描解析之 @ComponentScan 解析

ConfigurationClassPostProcessor 简单概述 Spring 中类的解析是非常重要的&#xff0c;因为工程中有很多类&#xff0c;并且被一些注解修饰&#xff0c;比如&#xff1a;Component、Bean、Import、PropertySource、ImportSource、Scope 等。 你在类或者方法上标注这些注解&a…

Tensorflow1 搭建Cuda11

前言 Tensorflow1中默认支持cuda10及以下的&#xff0c;最高的版本Tensorflow1.15默认使用cuda10&#xff1b;但是一些高性能的显卡&#xff0c;比如A100、3090等&#xff0c;它们只支持Cuda11的&#xff0c;这就不太友善了&#xff0c;毕竟不少项目依赖Tensorflow1搭建的。 …

linux基础学习-系统信息相关命令以及一些其他命令

主要是为了方便远程终端维护服务器时&#xff0c;查看服务器上当前的 系统日期和时间/磁盘空间占用情况/程序执行命令时间和日期 磁盘信息 -h&#xff1a;以人性化的方式显示文件大小进程信息 进程通俗地说就是当前正在执行的一个程序 ps默认只会显示当前用户通过终端启动的…

使用 openpyxl 在 Excel 电子表格中自动执行日常任务

花费数小时处理 Excel 中平凡的重复性任务。使用 Python 和 openpyxl 探索自动化。 像许多从事各种业务职能的人一样,我几乎每天都使用 Excel 来制作图表和分析。然而,其中一些图表需求相当平凡,涉及使用新的原始数据集创建新的工作表,该数据集需要以某种可预测的形式进行处…

采购管理基础知识:采购方法、模式与数据的作用

采购是任何企业的一个关键部分&#xff0c;是从外部来源获得货物和服务的过程。采购的目标是为企业获得尽可能好的价值。 采购流程可以通过使用各种工具进行优化。最重要的工具是采购管理软件。这种软件可以帮助企业跟踪他们的采购过程&#xff0c;并确保它们是有效的。 采购…

javaweb当中mysql要掌握的知识点(简单基础入门)

目录 1.mysql的数据模型 A.关系型数据库 B.mysql的客户端和数据库间的关系 C.数据库当中不同文件控制表的相关数据 2.使用注释 A.使用井号#加上要注释的文字 3.DDL---操作数据库 A.基本操作 B.创建表 C.修改表 D.给表添加数据 E.基础查询 F.排序查询语法 G.分页查询 4.…

linux下的环境变量

环境变量查看环境变量方法环境变量的组织方式通过代码如何获取环境变量 查看环境变量方法 环境变量的组织方式通过代码如何获取环境变量查看环境变量方法 环境变量的组织方式 通过代码如何获取环境变量 查看环境变量方法 ./常见的环境变量. 1️⃣ PATH:指定命令的搜索路径 2…

有哪些好用的建筑工程项目管理软件?

工程项目管理是建筑企业经营管理的核心业务&#xff0c;任何一家施工企业、任何一个工程管理团队&#xff0c; 无论是建立初创型企业&#xff0c;还是小公司开始进行业务扩张时&#xff0c;工程项目管理都至关重要。 针对行业痛点&#xff0c;推荐试试这款系统&#xff1a;ht…

银河麒麟V10系统NetworkManager服务启动失败的解决方法

目录 一、NetworkManger网络服务启动失败 二、故障定位过程 &#xff08;一&#xff09;重装NetworkManager未解决 &#xff08;二&#xff09;重装openssl未解决 三、解决方案 &#xff08;一&#xff09;修改/etc/ld.so.conf配置文件 &#xff08;二&#xff09;执行ld…

实操干货!专利的12种用处。

对于专利申请人和企业来说&#xff0c;为什么要申请专利以及申请到的专利能有什么作用&#xff1f; 答案可能会有很多种&#xff0c;小编在本文中列举了12种。你的理由是什么呢&#xff1f;可以在文后留言与我们进行互动交流。 几十年来中国专利申请数量已足足有几百万&#x…

C语言 CJSON使用实例

C语言 CJSON使用实例 提示&#xff1a;写完文章后&#xff0c;目录可以自动生成&#xff0c;如何生成可参考右边的帮助文档 文章目录C语言 CJSON使用实例前言一、cJSON实例1. json数据的封装2. json数据解析前言 提示&#xff1a;这里可以添加本文要记录的大概内容&#xff1a…

【小5聊】Sql Server时间转换和查询时间范围查询不正确的原因

最近在做时间方法封装的时候发现了一个问题&#xff01; 如果sql语句输出的时间字段转为了字符串输出&#xff0c;那么在使用此字段作为时间范围筛选时发现无效了&#xff0c;没法过滤对应的时间范围内记录 下面进行场景重现下 1、创建表 创建只有三个字段的表testTable&…

LeetCode:1760. 袋子里最少数目的球

解题思路&#xff1a; 看了很久也不知道该怎么下手&#xff0c;果断转去题解看答案&#xff0c;所实话官方的题解说的有些抽象&#xff0c;先买那是我自己看了别人的博客和思考后的一些思路&#xff1a; 1、为什么可以用二分查找&#xff1f; 题目要求你的开销是单个袋子里球…

滴滴前端常考vue面试题整理

谈谈对keep-alive的了解 keep-alive 可以实现组件的缓存&#xff0c;当组件切换时不会对当前组件进行卸载。常用的2个属性 include/exclude &#xff0c;2个生命周期 activated &#xff0c; deactivated vue和react的区别 > 相同点&#xff1a; 1. 数据驱动页面&#x…

jQuery DOM

文章目录jQuery DOM概述操作元素创建元素插入节点prepend()prependTo()append()appendTo()before()insertBefore()after()insertAfter()删除元素remove()detach()empty()复制元素clone()替换元素replaceWith()replaceAll()包裹元素wrap()wrapAll()wrapInner()遍历元素属性操作获…