java数据结构之哈希表

什么时哈希表

哈希表是根据关键码值(key-value)而直接进行访问的数据结构,它通过把关键码值映射到表的一个位置来访问记录,以加快查找的速度
直接来说数组就是一张哈希表
在这里插入图片描述
我们可以通过索引值对元素进行查找

常见的三种哈希结构

  • 数组
  • set集合
  • map(映射)

当我们遇到了一个要判断一个元素是否出现在集合里的时候,就要考虑哈希法了
但是哈希法是牺牲空间换取时间的,因为我们要使用额外的数组,set,map来存放数据,才能实现快速的查找。

哈希表之有效的字母异位词

tip:数组是简单的哈希表,但是数组的大小受限。

哈希表之 set

在这里插入图片描述

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

两个数组的交集

在这里插入图片描述

方法一、 三个哈希表求解

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Set<Integer> n1=new HashSet<>();
        Set<Integer> n2=new HashSet<>();
        for(int num1:nums1){
            n1.add(num1);
        }
        for(int num2:nums2){
            n2.add(num2);
        }
        Set<Integer> res=new HashSet<>();
        for(int n:n2){
            if(n1.contains(n)){
                res.add(n);
            }
        }
        int[] ans =new int[res.size()];
        int k=0;
        for(int r:res){
            ans[k]=r;
            k++;
        }
        return ans;
    }

}

方法二、

class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        Arrays.sort(nums1);
        Arrays.sort(nums2);
        int length1 = nums1.length, length2 = nums2.length;
        int index1 = 0, index2 = 0, index=0;
        int[] res = new int[length1+length2];
        while(index1 < length1 && index2 < length2){
            int num1=nums1[index1],num2=nums2[index2];
            if(num1==num2){
               if(index==0 || num1!=res[index-1]){
                   res[index++]=num1;
               }
                index1++;
                index2++;
            }else if(num1<num2){
                index1++;
            }else{
                index2++;
            }
        }
        return Arrays.copyOfRange(res,0,index);
    }
}

哈希表之快乐数

在这里插入图片描述
在这里插入图片描述
递归+哈希表

class Solution {
    Set<Integer> set = new HashSet<>();
    int pop =0;
    public boolean isHappy(int n) {
        return helper(n)==1?true:false;
    }
    public int helper(int n){
        if(n==1 ||set.contains(n)) return n;
        set.add(n);
        int sum =0;
        while(n%10!=0||n>0){
            pop = n%10;
            sum+=pop*pop;
            n=n/10;
        }
        return helper(sum);
    }
}

哈希表之map

map之两数之和、

在这里插入图片描述
这道题知道用map做 但是忘记map.containsKey了想了半天不知道怎么做 还是看解析会的 烦!

class Solution {
    public int[] twoSum(int[] nums, int target) {
        Map<Integer,Integer> map =new HashMap<>();
        for(int i =0;i<nums.length;i++){
            if(map.containsKey(target-nums[i])){
                return new int[] {map.get(target-nums[i]),i};
            }
            map.put(nums[i],i);
        }
        return new int [0];
    }
}

map之四数相加

在这里插入图片描述

class Solution {
    public int fourSumCount(int[] A, int[] B, int[] C, int[] D) {
        int n = A.length;
        Map<Integer,Integer> map = new HashMap<>();
        for(int i =0;i<n;i++){
            for(int j=0;j<n;j++){
                map.put(A[i]+B[j],map.getOrDefault(A[i]+B[j],0)+1);
            }
        }
        int count =0;
        for(int i=0;i<n;i++){
            for(int j=0;j<n;j++){
                if(map.containsKey(-C[i]-D[j])){
                    count+=map.get(-C[i]-D[j]);
                }
            }
        }
        return count;
    }
}

map之赎金信

在这里插入图片描述

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        Map<Character,Integer> map = new HashMap<>();
        for(int i =0;i<magazine.length();i++){
            map.put(magazine.charAt(i),map.getOrDefault(magazine.charAt(i),0)+1);
        }
        for(int i = 0;i<ransomNote.length();i++){
            if(!map.containsKey(ransomNote.charAt(i))||map.get(ransomNote.charAt(i))<=0){
                return false;
            }
            map.put(ransomNote.charAt(i),map.getOrDefault(ransomNote.charAt(i),0)-1);
        }
        return true;
    }
}

三数之和、混在map中的双指针

在这里插入图片描述

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        Arrays.sort(nums);
        List<List<Integer>> ans = new ArrayList<>();
        for(int l1=0;l1<nums.length-2;l1++){
        //去除相同元素
            if(l1>0 && nums[l1]==nums[l1-1]){
                    continue;
                }
            int rigth = nums.length-1; 
            for(int i=l1+1;i<nums.length-1;i++){
            // 去除相同元素
                if(i>l1+1 && nums[i]==nums[i-1]){
                    continue;
                }
                while (nums[l1]+nums[i]+nums[rigth]<0 && i<rigth){
                    i++;
                }
                while(nums[l1]+nums[i]+nums[rigth]>0 && i<rigth){
                    rigth--;
                }
                if(i==rigth){
                    break;
                }
                //当等于0时将元素装进链表
                if(nums[l1]+nums[i]+nums[rigth]==0){
                    List<Integer> res = new ArrayList<>();
                    res.add(nums[l1]);
                    res.add(nums[i]);
                    res.add(nums[rigth]);
                    ans.add(res);
                }
                
            }
        }
        return ans;
    }
}

四数之和、隐藏在map中的排序+双指针

在这里插入图片描述

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        Arrays.sort(nums);
        List<List<Integer>> res = new ArrayList<>();
        int length=nums.length;
        for(int i =0;i<length-3;i++){
            if(i>0 && nums[i]==nums[i-1]){
                continue;
            }
            if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
                break;
            }
            if (nums[i] + nums[length - 3] + nums[length - 2] + nums[length - 1] < target) {
                continue;
            }
            for(int j =i+1;j<length-2;j++){
                if(j>i+1 && nums[j]==nums[j-1]){
                    continue;
                }
                if (nums[i] + nums[i + 1] + nums[i + 2] + nums[i + 3] > target) {
                     break;
                }
                if (nums[i] + nums[j] + nums[length - 2] + nums[length - 1] < target) {
                    continue;
                }
                int right=length-1,left=j+1;
                while(left<right){
                    int sum = nums[i]+nums[j]+nums[left]+nums[right];
                    if(sum==target){
                        List<Integer> ans = new ArrayList<>();
                        ans.add(nums[i]);
                        ans.add(nums[j]);
                        ans.add(nums[left]);
                        ans.add(nums[right]);
                        res.add(ans);
                        while(left<right && nums[left]==nums[left+1]){
                            left++;
                        }
                        left++;
                        while(left<right && nums[right-1]==nums[right]){
                            right--;
                        }
                        right--;
                    }else if(sum<target){
                        left++;
                    }else{
                        right--;
                    }
                }
            }
        }
        return res;
    }
}

哈希表总结

  • 一般来说哈希表都是用来迅速判断一个元素是否出现在集合中
  • 哈希函数和哈希碰撞在哈希表中的作用
    • 哈希函数是把要传入的Key映射到符号表的索引上
    • 哈希碰撞处理有多个key映射到相同的索引上时的情景,处理碰撞的普遍方式是拉链法和线性探测法
  • 常见的三种哈希结构
    • 数组
    • set(集合)
    • map(映射)

数组作为哈希表的应用场景

数组是简单的哈希表,但是数组的大小是受限的,受到系统栈空间的限制,当数组空间大而哈希值比较少,特别分散,跨度较大时,使用数组就会造成空间浪费。

set作为哈希表的应用场景

当数组不行的时候 这时候就用set呗

map作为哈希表的应用场景

数组大小受限
set里面只能放一个元素
当我们需要对两个值进行记录时 就需要用到map 了

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值