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

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

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


相关文章
|
8月前
|
前端开发 Python
幸运哈希hash单双尾数大小竞猜游戏开发源码部署
def is_even_number(number): """判断一个整数是否为偶数""" return number % 2 == 0
|
8月前
|
存储 算法 安全
走进Python Hash函数的魔幻世界:解密哈希算法与防碰撞技术
走进Python Hash函数的魔幻世界:解密哈希算法与防碰撞技术
104 0
|
11月前
|
Shell
哈希竞猜游戏开发源码部署方案(成熟技术)
哈希竞猜游戏开发源码部署方案(成熟技术)
|
12月前
|
算法 安全 区块链
哈希竞猜游戏开发稳定版/哈希竞猜游戏系统开发案例详细/哈希竞猜游戏系统源码逻辑及分析
在区块链中,每个新区块都包含上一个区块经过科学方法算出来的数据指纹——哈希值。这个值让一个个区块之间形成了有着严格顺序关系的链条结构,一旦某个区块中的任何数据被篡改,该区块在下一个区块头部的数据指纹——哈希值就会变动,之后就无法衔接上来,也就不会被任何人认可。
|
存储 区块链 数据安全/隐私保护
Hash哈希竞猜游戏系统开发(区块链游戏开发案例)丨Hash哈希竞猜游戏系统开发(详细程序)丨源码方案
单向性(one-way),从预映射,能够简单迅速的得到散列值,而在计算上不可能构造一个预映射,使其散列结果等于某个特定的散列值,即构造相应的M=J(h)不可行。这样,散列值就能在统计上唯一的表征输入值,因此,密码学上的Hash又被称为”消息摘要(message digest)”,就是要求能方便的将”消息”进行”摘要”,但在”摘要”中无法得到比”摘要”本身更多的关于”消息”的信息。
|
存储 安全 区块链
Hash哈希竞猜游戏开发运营版丨哈希Hash竞猜游戏系统开发(开发案例)及源码规则
去中心化存储技术是一种新型存储技术,它改变了传统的集中式存储技术,将数据从单一位置移到多个位置,这样就消除了存储数据的中心机构或服务器的责任,增加了安全性和数据的有效存储,确保用户的数据安全性
|
存储 安全 Java
哈希竞猜游戏系统开发(hash哈希开发)丨哈希竞猜游戏开发成熟源码及运营版
 哈希表属于抽象数据结构,需要开发者按哈希表数据结构的存储要求进行API定制,对于大部分高级语言而言,都会提供已经实现好的、可直接使用的API,如JAVA中有MAP集合、C++中的MAP容器,Python中的字典……
|
人工智能 算法
哈希游戏系统开发详细方案丨哈希竞猜游戏开发技术逻辑(源码部署)
哈希游戏系统开发详细方案丨哈希竞猜游戏开发技术逻辑(源码部署)
110 0
|
算法
算法竞赛100天第四天 —— 设计哈希表(散列表)
算法竞赛100天第四天 —— 设计哈希表(散列表)
算法竞赛100天第四天 —— 设计哈希表(散列表)
|
NoSQL 数据挖掘 应用服务中间件
哈希游戏系统开发技术讲解
哈希游戏系统开发技术讲解
115 1