小白都能看懂的力扣算法详解——哈希表(一)

!!本篇所选题目及解题思路均来自​​​​​​代码随想录 (programmercarl.com)

一 LC242.有效的字母异位词

题目要求:

给定两个字符串 s 和 t ,编写一个函数来判断 t 是否是 s 的字母异位词。

注意:若 s 和 t 中每个字符出现的次数都相同,则称 s 和 t 互为字母异位词。

242. 有效的字母异位词 - 力扣(LeetCode)

题目分析:

本题可以使用暴力解法,即两个for循环遍历嵌套,统计a~z在s和t中各出现的次数,然后比较是否相等,听起来就知道时间复杂度不会低。那么我们换个角度考虑,可不可以用a~z作为索引值0~25,用次数统计作为数组中的元素呢?也就哈希表。这样我们只需要比较哈希表对应下标位置的元素是否相等就可以了。再进一步简化考虑,与其建立两个哈希表,依次比较,不如简化一下,使用一个哈希表完成,既然我们需要判断的仅仅是两个元素数值是否相等,那我们只要拿s中增加的数值减去t中增加的数值,如果最后的结果和原先相同,就说明s和t中的次数一样。整体思路完毕,接下来考虑细节。

首先考虑我们该如何构建哈希表?刚刚我们提到过,要用a~z作为索引值0~25,用次数统计作为数组中的元素。因为我们的数据量不大,且索引连续,所以我们直接采用数组作为底层实现就OK了。接下来考虑如何用a~z作为索引值,我们知道,在Java中的字符是用ASCII码表示的,a~z数值连续,而数组中的索引值从0开始连续,所以我们只要用所有字母减去字符a即可得到其对应的索引值。

代码实现如下:

    public boolean isAnagram(String s, String t) {
        int[] record = new int[26];
        for(int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;
        }
        for(int i = 0; i < t.length(); i++) {
            record[t.charAt(i) - 'a']--;
        }
        for(int i = 0; i < record.length; i++) {
            if( record[i] != 0) {
                return false;
            }
        }
        return true;
    }

 我们可以进一步优化代码,将两次循环合并为一个,毕竟先加谁先减谁无所谓,最后结果不变。但是需要注意合并循环需要先判断两个字符串长度是否相等,否则就会出现越界问题。

public boolean isAnagram(String s, String t) {
        // 首先判断两个字符串长度是否相等,不等直接返回false
        if(s.length() != t.length()) {
            return false;
        }
        int[] record = new int[26];
        for(int i = 0; i < s.length(); i++) {
            record[s.charAt(i) - 'a']++;
            record[t.charAt(i) - 'a']--;
        }
        for(int i = 0; i < record.length; i++) {
            if( record[i] != 0) {
                return false;
            }
        }
        return true;
    }

这道题目也可以使用sort()方法进行排序后直接比较,感兴趣的同学可以自己实现试一下。

二 LC349 两个数组的交集

题目描述: 给定两个数组 nums1 和 nums2 ,返回 它们的交集 。输出结果中的每个元素一定是 唯一 的。我们可以 不考虑输出结果的顺序 。

 题目分析:

本题和上题有异曲同工之妙,都是判断某个元素是否在一个集合中出现过。所以我们依旧可以沿用上题的思路,唯一的难点在于如何实现“去重”。根据官方的提示,可以看到:

  • 1 <= nums1.length, nums2.length <= 1000
  • 0 <= nums1[i], nums2[i] <= 1000

 两个数组的长度及元素内容都有范围限定,因此可以直接使用数组作为底层实现。数组长度略大于1001即可。这里我们把情况考虑得更全面一点,不考虑对于数组长度和元素大小的限定条件,则需要使用set实现。set适合索引值数值分散或很大的情况,因为set的索引值无需像数组一样必须连续。解题思路也很简单,遍历nums1,将nums1中存在的索引对应的数值置为1(其他默认为0),由此得到的hash表即为一个记录了nums1所有元素去重后的结果的表。之后再次遍历nums2,判断其中存在的索引对应的值是否为1,如果为1说明该索引为两个数组的交集,将其存在结果集中即可。这里需要注意,我们的结果集也需要是一个hash数组,因为我们同样需要实现“去重”的操作。最后将结果集转换为数组即可。

代码实现:

public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> set1 = new HashSet<>(); // 
        Set<Integer> resSet = new HashSet<>(); // 结果集
        //遍历数组1,将数组1中的元素存储进去
        for (int i : nums1) {
            set1.add(i);
        }
        //遍历数组2,判断哈希表中是否存在该元素
        for (int i : nums2) {
            if (set1.contains(i)) {
                resSet.add(i);
            }
        }
        // 将set转换成数组
        int[] arr = new int[resSet.size()];
        int j = 0;
        for(int i : resSet){
            arr[j++] = i;
        }
        
        return arr;
    }

使用数组实现的代码如下,因为数组不好实现去重,所以我们直接使用两个数组分别将nums1、nums2中存在值的索引对应的数值置为1,之后比较相同索引值位置的元素是否均为1,若均为1则表示该值为交集中的元素: 

  public int[] intersection(int[] nums1, int[] nums2) {
        int[] hash1 = new int[1002];
        int[] hash2 = new int[1002];
        for(int i : nums1)
            hash1[i]++;
        for(int i : nums2)
            hash2[i]++;
        List<Integer> resList = new ArrayList<>();
        for(int i = 0; i < 1002; i++)
            if(hash1[i] > 0 && hash2[i] > 0)
                resList.add(i);
        int index = 0;
        int res[] = new int[resList.size()];
        for(int i : resList)
            res[index++] = i;
        return res;
    }

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

阿里云服务器镜像是什么?如何选择镜像?

阿里云服务器镜像怎么选择&#xff1f;云服务器操作系统镜像分为Linux和Windows两大类&#xff0c;Linux可以选择Alibaba Cloud Linux&#xff0c;Windows可以选择Windows Server 2022数据中心版64位中文版&#xff0c;阿里云服务器网aliyunfuwuqi.com来详细说下阿里云服务器操…

社交商业策略:揭秘Facebook Shops的成功之道

随着数字化时代的不断发展&#xff0c;社交媒体已经成为了商业活动的重要平台之一。在这个趋势下&#xff0c;Facebook作为全球最大的社交媒体平台之一&#xff0c;不仅仅是人们交流互动的场所&#xff0c;更成为了商家开展电子商务的重要渠道。其中&#xff0c;Facebook Shops…

python毕设选题 - 大数据商城人流数据分析与可视化 - python 大数据分析

文章目录 0 前言课题背景分析方法与过程初步分析&#xff1a;总体流程&#xff1a;1.数据探索分析2.数据预处理3.构建模型 总结 最后 0 前言 &#x1f525; 这两年开始毕业设计和毕业答辩的要求和难度不断提升&#xff0c;传统的毕设题目缺少创新和亮点&#xff0c;往往达不到…

如何在Windows 10中停止正在进行的更新?这里有你需要知道的细节

本文介绍如何取消正在进行的Windows更新。说明适用于Windows 10家庭版和专业版。 如何在Windows下载更新后取消更新 如果你还没有完全安装Windows 10更新&#xff0c;但你的电脑已经下载了该文件&#xff0c;并且关闭和重置选项已更改为“更新并关闭”和“更新并重新启动”&a…

EI级 | Matlab实现TCN-GRU-MATT、TCN-GRU、TCN、GRU多变量时间序列预测对比

EI级 | Matlab实现TCN-GRU-MATT、TCN-GRU、TCN、GRU多变量时间序列预测对比 目录 EI级 | Matlab实现TCN-GRU-MATT、TCN-GRU、TCN、GRU多变量时间序列预测对比预测效果基本介绍程序设计参考资料 预测效果 基本介绍 【EI级】Matlab实现TCN-GRU-MATT、TCN-GRU、TCN、GRU多变量时间…

消息中间件之RocketMQ源码分析(十)

Namesrv启动流程 第一步:脚本和启动参数配置。 启动命令 nohup ./bin/mqnamesrv -c ./conf/namesrv.conf > dev/null 2>&1 & 通过脚本配置启动基本参数&#xff0c;比如配置文件路径、JVM参数&#xff0c;调用NamesrvStartup.main()方法&#xff0c;解析命令行的…

斯坦福大学全能家政服务机器人Mobile ALOHA以及“小群体大智慧”Zooids集群机器人

斯坦福大学成功研发出低成本自主进化克隆人类行为和任务的能力全能型家政服务机器人。 原文标题: 【Mobile ALOHA-Learning Bimanual Mobile Manipulation with Low-Cost Whole-Body Teleoperation】 论文链接:【Mobile ALOHA (mobile-aloha.github.io)】。 以及由斯坦福大学…

【C项目】无头单向不循环链表

简介&#xff1a;本系列博客为C项目系列内容&#xff0c;通过代码来具体实现某个经典简单项目 适宜人群&#xff1a;已大体了解C语法同学 作者留言&#xff1a;本博客相关内容如需转载请注明出处&#xff0c;本人学疏才浅&#xff0c;难免存在些许错误&#xff0c;望留言指正 作…

代码随想录算法训练营第三十六天|435. 无重叠区间 763.划分字母区间 56. 合并区间

435. 无重叠区间 链接&#xff1a;力扣&#xff08;LeetCode&#xff09;官网 - 全球极客挚爱的技术成长平台 细节&#xff1a; 1. 这道题目和 452.用最少数量的箭引爆气球 &#xff0c;452中的弓箭数量其实就是 无重叠区间的数量&#xff0c;用总的区间数减去 无重叠区间的数…

C++入门学习(二十九)goto语句

在C中&#xff0c;goto语句是一种控制流语句&#xff0c;用于无条件地转移到程序中指定的行。goto语句的使用通常是不推荐的&#xff0c;因为它可能导致代码结构变得混乱、不易理解和维护。然而&#xff0c;在某些特殊情况下&#xff0c;goto语句可能是一种有效的解决方法。 示…

day2 2/19

1> 使用fread和fwrite完成两个文件的拷贝 #include<myhead.h> int main(int argc, const char *argv[]) {FILE*fp1NULL;FILE*fp2NULL;if((fp1fopen("./ggb.bmp","r"))NULL){perror("fopen error");return -1;}if((fp2fopen("./bl…

为什么你用的redis没有出现雪崩,击穿,穿透

一、前言 在大规模并发访问系统中&#xff0c;如果你的系统用到redis&#xff0c;在面试的时候面试官往往会问你的系统有没有出现雪崩&#xff0c;击穿&#xff0c;穿透这样的场景&#xff0c;然后是怎样解决的。博主也经常反复温习redis的特性&#xff0c;总是被雪崩&#xf…

MySQL数据库基础(十):DQL数据查询语言

文章目录 DQL数据查询语言 一、数据集准备 二、select查询 三、简单查询 四、条件查询 1、比较查询 2、范围查询 3、逻辑查询 4、模糊查询 5、非空查询 五、排序查询 六、聚合查询 七、分组查询与having子句 1、分组查询介绍 2、group by的使用 3、group by 聚…

Linux超详细笔记

文章目录 Linux学习笔记操作系统Linux初识Linux的诞生Linux内核Linux发行版 虚拟机VMware安装远程连接Linux系统FinalShellFinalShell连接Linux WSL配置UbuntuLinux常用命令1.入门2.ls命令cd命令3.pwd命令4.相对路径和绝对路径5.mkdir命令6.文件操作命令&#xff08;1&#xff…

初始HTTP协议

一、http协议 1、http相关概念 互联网&#xff1a;是网络的网络&#xff0c;是所有类型网络的母集因特网&#xff1a;世界上最大的互联网网络。即因特网概念从属于互联网概念。习惯上&#xff0c;大家把连接在因特网上的计算机都成为主机。万维网&#xff1a;WWW&#xff08;…

NodeLocal DNS介绍及部署应用

1 NodeLocal DNS是什么&#xff1f; NodeLocal DNSCache 通过在集群节点上运行一个 DaemonSet 来提高 clusterDNS 性能和可靠性。处于 ClusterFirst 的 DNS 模式下的 Pod 可以连接到 kube-dns 的 serviceIP 进行 DNS 查询。通过 kube-proxy 组件添加的 iptables 规则将其转换为…

函数模板与模板的特例化

函数模板 模板的意义&#xff1a;对类型进行参数化 模板类型参数 c使用class、typename关键字定义模板类型参数 函数模板&#xff1a;不进行编译&#xff0c;因为类型还不知道 template <typename T>//定义一个模板参数列表 bool compare(T a,T b)//compare是一个函…

通用二进制方式安装MySQL8.0.x

一、必要说明 1、系统&#xff1a;openEuler操作系统 2、版本&#xff1a;MySQL - 8.0.36 3、下载地址&#xff1a;https://dev.mysql.com/get/Downloads/MySQL-8.0 二、安装步骤 1、下载glibc版本的Mysql [rootnode2 ~]# wget -c https://dev.mysql.com/get/Downloads/MySQ…

C++ bfs反向建图(六十)【第七篇】

今天我们来学习一下bfs反向建图 1.bfs的反向建图 我们之前在图上求最短路都是求从起点出发到每个点的最短路&#xff0c;不过有时候我们也会遇到让求每个点到终点的最短路的问题&#xff0c;此时我们可以怎么做呢&#xff1f; 如果从每个点出发&#xff0c;用 BFS 搜索到终点…

测试开发【Mock平台】13基础:拦截器服务实现(四) 简单规则匹配逻辑

【Mock平台】为系列测试开发教程&#xff0c;从0到1编码带你一步步使用Spring Boot 和 Antd React框架完成搭建一个测试工具平台&#xff0c;希望作为一个实战项目对各位的测试开发学习之路有帮助&#xff0c;关注公众号发送“mock”获取github项目源码地址&#xff0c;大奇一个…
最新文章