哈希表及其应用

哈希表

数组、map以及set
一般哈希碰撞有两种解决方法, 拉链法和线性探测法。
使用线性探测法,一定要保证tableSize大于dataSize。 我们需要依靠哈希表中的空位来解决碰撞问题
注意:如果在做面试题目的时候遇到需要判断一个元素是否出现过的场景也应该第一时间想到哈希法!
参考文献: 代码随想录

leetcode 242 有效的字母异位词

利用数组实现哈希表。注意C++中提取字符串的每个字符可以用字符串名[i]的方法,而Java中要用字符串名.charAt(i)的方法。由于数组的大小可控,故可直接用数组下标做哈希映射。

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


    }
}

leetcode 349 两个数组的交集

注意:使用HashSet容器来求解。容器中的类型需要是诸如String、Integer、Object、Date以及Void这些引用类型。最后将结果转换成数组输出,数组的initCapacity可以由容器的.size()方法获取。

import java.io.*;
import java.util.*;
class Solution {
    public int[] intersection(int[] nums1, int[] nums2) {
        //Java中HashSet是基于HashMap实现的,初始容量是16,默认的加载因子是0.75
        Set<Integer> result = new HashSet<Integer>();
        Set<Integer> nums = new HashSet<Integer>();
        for(int i = 0; i < nums1.length; i++){
            nums.add(nums1[i]);//不会添加重复的元素
        }
        for(int i = 0; i < nums2.length; i++){
            if(nums.contains(nums2[i])){
                result.add(nums2[i]);
            }
        }
        int[] result2 = new int[result.size()];
        int j = 0;
        for(int i : result){
            result2[j] = i;
            j++;
        }
        return result2;


    }
}

leetcode 1 两数之和

用HashMap存储已经遍历过的数。其中key存放数值,value存放数值的下标。
注意HashMap中containsKey()方法和get()方法的使用。

class Solution {
    public int[] twoSum(int[] nums, int target) {
        HashMap<Integer,Integer> map = new HashMap<Integer, Integer>();
        int[] result = new int[2];
        for(int i = 0; i < nums.length; i++){
            int j = target - nums[i];
            if(map.containsKey(j)){
                result[0] = map.get(j);
                result[1] = i;
                map.put(nums[i],i);//将元素自己也加入到map中
            }
            map.put(nums[i],i);

        }
        return result;

    }
}

四数相加

不用考虑去重。本题也使用HashMap,其中key存放数值,value存放该数值出现的次数。
注意用Java进行map[a+b]++操作时(将对应数值的出现次数加1),利用变量val赋值时要用++val(具体见代码)。

class Solution {
    public int fourSumCount(int[] nums1, int[] nums2, int[] nums3, int[] nums4) {
        HashMap<Integer,Integer> map = new HashMap<Integer,Integer>();
        int result = 0;
        for(int i = 0; i < nums1.length; i++){
            for(int j = 0; j< nums2.length; j++){
                if(map.containsKey(nums1[i]+nums2[j])){
                    int val = map.get(nums1[i]+nums2[j]);
                    map.put(nums1[i]+nums2[j],++val);//这里时++val
                }else{
                    map.put(nums1[i]+nums2[j],1);//第一次出现,故表示次数的value = 1
                }

            }
        }
        for(int i = 0;i < nums3.length;i++){
            for(int j = 0;j < nums4.length;j++){
                int target = 0 - (nums3[i]+nums4[j]);
                if(map.containsKey(target)){
                    result += map.get(target);
                }
            }
        }
        return result;

    }
}

leetcode 15 三数之和

不建议用hash法去做,因为去重的细节太复杂。利用双指针法,先将数组升序排序。
对a去重:nums[i] == nums[i - 1]。对b和c的去重一定要放在已经获得一个结果之后的代码中,否则会遗漏{0,0,0,0,0}这种情况。

class Solution {
    public List<List<Integer>> threeSum(int[] nums) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);
        for(int i = 0; i < nums.length; i++){
             if(nums[i] > 0){return result;}
             //对a去重
             if(i > 0 && nums[i] == nums[i - 1]){continue;}
             int left = i + 1;
             int right = nums.length - 1;
             while(left < right){
                if(nums[i] + nums[left] + nums[right] < 0){
                    left++;
                }else if(nums[i] + nums[left] + nums[right] > 0){
                    right--;
                }else{
                    result.add(Arrays.asList(nums[i], nums[left], nums[right]));
                    //对b和c去重
                    while(left < right && nums[left] == nums[left + 1]){left++;}
                    while(left < right && nums[right] == nums[right - 1]){right--;}
                    left++;
                    right--;
                }
             }
             
        }
        return result;

    }
}

leetcode 18 四数之和

在三数之和的基础之上,外加一层for循环。注意target有可能是负数。故二级剪枝时应该将nums[i]+nums[k]看作一个整体,剪枝的条件是:nums[i]+nums[k] > target && nums[i]+nums[k] > 0 &&target > 0

class Solution {
    public List<List<Integer>> fourSum(int[] nums, int target) {
        List<List<Integer>> result = new ArrayList<>();
        Arrays.sort(nums);//将数组升序排列
        for(int k = 0; k < nums.length; k++){
            //一级剪枝和去重
            if(nums[k] > target && nums[k] > 0){return result;}
            if(k > 0 && nums[k] == nums[k - 1]){continue;}
            for(int i = k + 1; i < nums.length; i++){
                //二级剪枝和去重
                // if(nums[k] + nums[i] > target && nums[k] + nums[i] > 0 && target > 0 )
                // {return result;}
                if(i > k + 1 && nums[i] == nums[i - 1]){continue;}
                //定义双指针left和right
                int left = i + 1;
                int right = nums.length - 1;
                //遍历在nums[k]与nums[i]固定的前提下的nums[left]和nums[right]
                while(left < right){
                    if((nums[k] + nums[i] + nums[left] + nums[right]) < target){
                        left++;
                    } else if((nums[k] + nums[i] + nums[left] + nums[right]) > target){
                        right--;
                    }else{
                        result.add(Arrays.asList(nums[k], nums[i], nums[left], nums[right]));
                        while(left < right && nums[left] == nums[left + 1]){left++;}
                        while(left < right && nums[right] == nums[right - 1]){right--;}
                        //没有进while循环时也要记得移动left和right指针
                        left++;
                        right--;
                    }

                }
            }

        }
         return result;

    }
}

leetcode 202 快乐数

根据题意,若不是快乐数,则sum的值会出现循环,每一次都将sum值存入HashSet中,若HashSet包含出现过的sum,则说明不是快乐数。

class Solution {
    public boolean isHappy(int n) {
        HashSet<Integer> sumSet = new HashSet<Integer>();
        int sum = 0;
        while(n != 0){
            sum = sum + (n % 10) * (n % 10);
            n = n / 10;
            if(n == 0){
                if(sumSet.contains(sum)){
                    return false;
                
                }else if(sum == 1){
                    break;
                
                }else{
                    sumSet.add(sum);
                    n = sum;
                    sum = 0;
                }       
            }
        }
        return true;
        
    }
}

leetcode 383 赎金信

利用有效的字母异位词的思想。

class Solution {
    public boolean canConstruct(String ransomNote, String magazine) {
        int[] nums1 = new int[26];
        int[] nums2 = new int[26];
        char[] chars1 = ransomNote.toCharArray();
        char[] chars2 = magazine.toCharArray();
        for(int i = 0; i < chars1.length; i++){
            nums1[chars1[i] - 'a']++;
        } 
        for(int i = 0; i < chars2.length; i++){
            nums2[chars2[i] - 'a']++;
        } 
        for(int i = 0; i < 26; i++){
            if(nums2[i] >= nums1[i]){
                continue;
            }else{
                return false;
            }
        }
        return true;


    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
哈希表(Hash Table),也称为散列表,是一种高效的数据结构,用于存储和查找键值对。它通过将键映射到一个固定大小的数组索引来实现快速的插入、删除和查找操作。 哈希表的核心思想是利用哈希函数将键转换为数组索引。哈希函数接收键作为输入,并生成一个对应的索引值。具有相同索引值的键值对会被存储在数组的同一个位置上,这个位置就是哈希表中的桶(bucket)。当需要查找特定键的值时,再次应用哈希函数即可快速定位到对应的桶,并返回值。 哈希表的主要优点是快速插入、删除和查找操作的时间复杂度通常为O(1)。然而,在某些情况下,由于哈希冲突(不同键对应相同索引),可能会导致性能下降。为了解决哈希冲突,常见的解决方法是使用链表或其他数据结构来处理冲突的元素,形成链地址法或开放地址法。 应用场景: - 缓存:哈希表常用于缓存系统中,可以通过将数据存储在内存中的哈希表中来加快访问速度。 - 数据索引:哈希表常用于构建索引,例如数据库中的索引,可以快速定位和检索数据。 - 字典:哈希表可以用于实现字典,其中键值对可以表示词汇和其对应的定义。 - 唯一性检查:哈希表可以用于检查元素的唯一性,例如在网站用户注册中检查用户名是否已存在。 - 分布式存储:哈希表在分布式系统中被广泛使用,用于数据的分片和路由。 总之,哈希表是一种高效的数据结构,适用于需要快速插入、删除和查找操作的场景。它在各种应用中都发挥着重要的作用。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值