【哈希系列】舍友担心期末考睡不着,我连夜准备了这套哈希全套专题(上)

简介: 今天为大家带来一套哈希套题的专项训练题型,哈希表在数据结构中占有非常重要的地位。很多同学总是学习了理论知识,缺乏实际使用。正所谓将军都是从战场上杀出来的,想要成为哈希大神,还得疯狂刷题。问题是很多同学他根本不知道如何找到合适的题目来训练,而且没有配套的答案解析。这里我为大家精心筛选了数道哈希经典例题,题目较为基础,能让初学者充分感受哈希的魅力,配上详细的代码思路解析,定让你收获满满。建议收藏,防止找不到,可以反复练习,题目总链接在末尾

🍍1. 刷题与观看须知


       任何算法题目,你光看不自己去实现,都不算真正地学到了自己的知识库中。所以推荐兄弟们有空要通过题目链接一定要去自己尝试写。而且即使做出来了,也要去想办法优化自己的代码,即使是同样的方法,也许别人写的更加简洁易懂。也要去学习复杂度更低更优秀的解题方法,正所谓条条大路通罗马,我走了较远的那条路,但我们到了终点也该学习一下更短的路,不然下次仍然会走最远的路,这就脱离了学习的本质了。  


🍍2. 力克哈希,鏖战力扣


🐄1.存在重复元素


给定一个整数数组,判断是否存在重复元素。


如果存在一值在数组中出现至少两次,函数返回 true 。如果数组中每个元素都不相同,则返回 false 。


题目链接:存在重复元素https://leetcode-cn.com/problems/contains-duplicate/              

          题目分析:这个题目的名称,就已经是用哈希的标志了,拿这道题作为哈希的入门实在是最好不过了,哈希经典的以空间换时间(升高空间复杂度降低时间复杂度)。我也贴上排序做法的代码供大家对比。


方法1:排序


          时间复杂度O(nlongn):主要是排序的开销,如果是朴素的两层for循环暴力遍历开销为O(n^2)


          空间复杂度O(nlogn):排序的开销


class Solution {
    public boolean containsDuplicate(int[] nums) {
            //排序
            Arrays.sort(nums);
            int n=nums.length;        
            //看相邻的是否相等
            for(int i=0;i<n-1;i++){
                if(nums[i]==nums[i+1]){
                    return true;
                }
            }
            return false;
    }
}


方法2:哈希判重


          复杂度O(n):n为nums的长度,主要是循环的耗时


          复杂度O(n):n为nums的长度,主要是哈希的开销,最差的情况下数组全部都被放入set中


class Solution {
    public boolean containsDuplicate(int[] nums) {
        Set<Integer> set=new HashSet<Integer>();
        int n=nums.length;
        for(int i=0;i<n;i++){
            if(!set.contains(nums[i])){
                set.add(nums[i]);
            }else{
                return true;
            }
        }
        return false;
    }
}


🐏2.存在重复元素||


给定一个整数数组和一个整数 k,判断数组中是否存在两个不同的索引 i 和 j,使得 nums [i] = nums [j],并且 i 和 j 的差的 绝对值 至多为 k。


题目链接:存在重复元素|| https://leetcode-cn.com/problems/contains-duplicate-ii/      

            题目分析:这道题是第一题的进阶,在第一题的要求上做了一定的要求,更加适合哈希的做法,因为涉及到索引,我们需要把set转换成map,key保存值,value保存下标索引。


方法1:哈希判重


            时间复杂度O(n):n为nums的长度,主要是循环的耗时,最差情况整个数组遍历完。


            空间复杂度O(n):n为nums的长度,主要为哈希的开销


class Solution {
    public boolean containsNearbyDuplicate(int[] nums, int k) {
        //key存值,value存下标
        Map<Integer,Integer> map=new HashMap<>();
        int n=nums.length;
        for(int i=0;i<n;i++){
            //没有这个数,存入map中
            if(!map.containsKey(nums[i])){
                map.put(nums[i],i);
            }else{
                //不满足题目的要求
                if(map.get(nums[i])-i>k||i-map.get(nums[i])>k){
                    //更新下标,防止这个数后面再出现就满足要求了
                    map.put(nums[i],i);                   
                }else{
                    //满足要求返回true
                    return true;
                }
            }
        }   
        //结束完说明没有返回false
        return false;        
    }
}


🐠3.有效的字母异位词


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


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


题目链接:有效的字母异位词https://leetcode-cn.com/problems/valid-anagram/        

       题目解析:这道题目的意思很简单,就是字符串出现的字母和频率都相同即可,这是非常经典的使用哈希的特征。但这里我想让大家知道,排序才是最简单的方法,也是大家都应该想到的。不仅是数字可以排序,字母也是可以排序的,如果是有效的字母异位词,排序后的char[]肯定一模一样。但是大家一定要知道。既然是哈希专场,利用哈希大家也一定要会做。


方法1:转换为char[]排序后进行对比。


       时间复杂度O(nlogn):排序的时间是O(nlogn),遍历的世界是O(n),加起来还是算O(nlogn)


       空间复杂度:O(logn)。排序API需要O(logn)的复杂度,而且如果是Java语言的话,由于String的不可变性,还得再用O(n)的空间来拷贝数组。


class Solution {
    public boolean isAnagram(String s, String t) {
        //先将字符串都转换为字符数组
        char[] arr1=s.toCharArray();
        char[] arr2=t.toCharArray();
        //sort函数也可以传入字符数组
        Arrays.sort(arr1);
        Arrays.sort(arr2);
        //Arrays有一个重写的equals方法
        //可以直接比较两个数组是否完全一样
        return Arrays.equals(arr2,arr1);
    }
}


方法2:利用数组来映射哈希。我们要知道数组也是哈希的提现,索引下标相当于key,存储的值相当于value。我们可以用一个长度为26的char数组来存在从a到z每个数字出现的频率,在遍历s时遇到的每个字符出现的次数+1,遍历t时减1。如果最后数组中不全为0则说明不是有效的字母异位词。


       时间复杂度O(n):n为较长一条字符串的长度,主要是遍历


       空间复杂度O(1):常数级的数组消耗也只算O(1)


class Solution {
    public boolean isAnagram(String s, String t) {
        //从下标0存储a开始来存储每个数字出现的频率
        int[] arr=new int[26];
        //遍历字符串s
        for(int i=0;i<s.length();i++){
            //s.charAt(i)-'a'是为了找到每个字符对应的索引下标
            arr[s.charAt(i)-'a']++;
        }
        for(int i=0;i<t.length();i++){
            arr[t.charAt(i)-'a']--;
        }
        //遍历到不为0的说明有字母数量不相等,返回false
        for(int i=0;i<arr.length;i++){
            if(arr[i]!=0) return false;
        }
        //遍历结束没返回false说明是有效的字母异位,返回true
        return true;
    }
}


相关文章
|
缓存 网络协议 数据库连接
C/S架构中HTTP错误状态码原因分析及解决办法
HTTP(Hypertext Transfer Protocol)是用于在客户端和服务器之间传输数据的协议。当在浏览器或其他HTTP客户端中访问网页时,可能会发生各种访问报错。我们需要根据网页提供的错误状态码分析错误原因,以找到相对应的解决办法。
1140 0
|
算法 程序员 Go
[软件工程导论(第六版)]第6章 详细设计(复习笔记)
[软件工程导论(第六版)]第6章 详细设计(复习笔记)
|
12月前
|
人工智能
从零开始学写歌词:关键技巧和方法一网打尽,妙笔生词AI智能写歌词软件
从零开始学写歌词,掌握关键技巧和方法,探索歌词创作的奇妙世界。借助“妙笔生词智能写歌词软件”,利用AI智能生成、优化和解读歌词等功能,轻松找到灵感,提升创作水平,创作出动人的歌词。
|
11月前
|
安全 测试技术 网络安全
免费的ip地址证书有吗,哪里申请
在网络安全日益重要的今天,SSL证书成为保护网站数据传输安全的关键工具。对于拥有公网IP地址的用户,申请免费IP地址SSL证书是提升网站安全性的经济有效方式。本文介绍了通过知名CA机构如JoySSL申请免费IP地址SSL证书的步骤和注意事项,帮助用户轻松获得并安装证书,确保网站数据的安全传输。
|
存储 SQL 关系型数据库
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
MySQL调优主要分为三个步骤:监控报警、排查慢SQL、MySQL调优。 排查慢SQL:开启慢查询日志 、找出最慢的几条SQL、分析查询计划 。 MySQL调优: 基础优化:缓存优化、硬件优化、参数优化、定期清理垃圾、使用合适的存储引擎、读写分离、分库分表; 表设计优化:数据类型优化、冷热数据分表等。 索引优化:考虑索引失效的11个场景、遵循索引设计原则、连接查询优化、排序优化、深分页查询优化、覆盖索引、索引下推、用普通索引等。 SQL优化。
1481 15
【MySQL调优】如何进行MySQL调优?从参数、数据建模、索引、SQL语句等方向,三万字详细解读MySQL的性能优化方案(2024版)
|
JavaScript Java 测试技术
基于SpringBoot+Vue+uniapp的二手物品交易平台的详细设计和实现(源码+lw+部署文档+讲解等)
基于SpringBoot+Vue+uniapp的二手物品交易平台的详细设计和实现(源码+lw+部署文档+讲解等)
129 1
|
机器学习/深度学习 算法
区间预测 | MATLAB实现QRLSTM长短期记忆神经网络分位数回归时间序列区间预测
区间预测 | MATLAB实现QRLSTM长短期记忆神经网络分位数回归时间序列区间预测
|
消息中间件 Serverless Kafka
基于 EventBridge 轻松搭建消息集成应用
基于 EventBridge 轻松搭建消息集成应用
22313 71
|
XML 安全 网络安全
SSRF(服务器端请求伪造)
SSRF(服务器端请求伪造)攻击,如何进行内网穿透
246 1
|
分布式计算 资源调度 Java
Flink教程(03)- Flink环境搭建(上)
Flink教程(03)- Flink环境搭建(上)
282 0