5. 哈希表

哈希表

基本都是参考这个up主,非常感谢

1. 相关概念:

概念

散列表(Hash table,也叫哈希表),是根据关键码值(Key value)而直接进行访问的数据结构。也就是说,它通过把关键码值映射到表中一个位置来访问记录,以加快查找的速度。这个映射函数叫做散列函数,存放记录的数组叫做散列表。

给定表M,存在函数f(key),对任意给定的关键字值key,代入函数后若能得到包含该关键字的记录在表中的地址,则称表M为哈希(Hash)表,函数f(key)为哈希(Hash) 函数。


原理:key —> 哈希函数 —> 内存地址(—–> key/value 对应的内存地址)

Java中的是HashMap

哈希碰撞

不同key值通过一个哈希函数得到相同的内存地址

解决方法:

​ 链地址法:产生hash冲突后在存储数据后面加一个指针,指向后面冲突的数据

2. 哈希表的四种功能

1. 访问(Access):没有

没有这个概念,因为没有下标,有的是key

2. 搜索(Search):O(1)

对key进行搜索,如果产生碰撞,时间复杂度是O(K),K是碰撞元素的个数

3. 插入(Insert): O(1)

通过key插入

4. 删除(Delete):O(1)

通过key删除

3.常用操作

两种方法:

  1. 数组,把数组索引当作哈希表的key,元素当作哈希表的value
  2. HashMap
1.创建哈希表

在这里插入图片描述

1.数组方式

2.Java中HashMap方式,其中Integer是key的类型,String是value的类型

2.添加元素

在这里插入图片描述

1.数组:将值赋给对应的索引

2.HashMapput(key,value)

3.更新元素

在这里插入图片描述

和添加一样,将原来的元素给覆盖了

1.数组:将修改的值赋给对应的索引

2.HashMapput(key,value)

4.删除元素

在这里插入图片描述

remove(key)

5.获取元素

在这里插入图片描述

1.数组:直接获取索引

2.HashMapget(key)

6.检查key是否存在

在这里插入图片描述

containsKey(key)

7.哈希表的长度

在这里插入图片描述

size()

8.哈希表是否还有元素

在这里插入图片描述

isEmpty()

4.Leetcode

217.存在重复元素

在这里插入图片描述

三种方法:

  1. HashMap
  2. 数组
  3. HashSet

方法一: HashMap

public boolean containsDuplicate(int[] nums) {
    if (nums == null || nums.length == 0) {
        return false;
    }
    HashMap<Integer, Integer> map = new HashMap<>();
    for (int num : nums) {
        if (map.containsKey(num)) {
            map.put(num, map.get(num) + 1);
        } else {
            map.put(num, 1);
        }
    }
    for (int k : map.keySet()) {
        if (map.get(k) > 1) {
            return true;
        }
    }
    return false;
}

方法二:

  1. 对数组进行排序
  2. 设置一个指针(指向前一个元素)进行遍历
public boolean containsDuplicate1(int[] nums) {
    Arrays.sort(nums);
    for (int i = 0; i < nums.length - 1; i++) {
        if (nums[i] == nums[i + 1]) {
            return true;
        }
    }
    return false;
}

方法三:

HashSet

HashSet是实现Set<E>接口的一个实体类,数据是以哈希表的形式存放的,里面的不能包含重复数据。Set接口是一种一个不包含重复元素的 collection。

在这里插入图片描述

public boolean containsDuplicate2(int[] nums) {
   /* 
    if (nums == null || nums.length == 0) {
        return false;
    }
    */
    
    HashSet<Integer> set = new HashSet<>();
    for (int num : nums) {
        set.add(num);
    }
    return set.size() == nums.length ? false : true;
}

389.找不同

在这里插入图片描述

方法一:

运用数组,用到ASCII码,a=97,A=65

  1. 因为两个字符串都包含小写字母,所以数组长度是26

  2. 巧用ASCII码,让每个字符的ASCII码-a的ASCII码,得到的就是数组的下标

  3. 遍历两个字符串,一个加一一个减一

    如果最后元素的结果<0,就返回该元素

package qi.hashmap;

/*
首先遍历字符串 s,对其中的每个字符都将计数值加 1;然后遍历字符串 t,对其中的每个字符都将计数值减 1。当发现某个字符计数值为负数时,说明该字符在字符串 tt中出现的次数大于在字符串 s 中出现的次数,因此该字符为被添加的字符。
*/
public class LeetCode389 {
    public char findTheDifference(String s, String t) {
        int[] cnt = new int[26];
        for (int i = 0; i < s.length(); ++i) {
            char ch = s.charAt(i);
            cnt[ch - 'a']++;
        }
        for (int i = 0; i < t.length(); ++i) {
            char ch = t.charAt(i);
            cnt[ch - 'a']--;
            if (cnt[ch - 'a'] < 0) {
                return ch;
            }
        }
        return ' ';
    }

}

方法二:

求和

  1. 定义两个变量接收两个字符中所有字符的ASCII相加的值

  2. 用长的t减去短的s,差值在转为行的ASCII码

public char findTheDifference1(String s, String t) {
    int as=0;
    int at=0;
    for (int i = 0; i < s.length(); i++) {
        as+=s.charAt(i);
    }
    for (int i = 0; i < t.length(); i++) {
        at+=t.charAt(i);
    }
    return (char) (at-as);
}

496.下一个更大元素

在这里插入图片描述

用栈和哈希表实现

  1. 遍历nums2,当栈不为空并且nums2中的元素 > 栈顶元素

    ​ 将栈顶元素弹出(作为key)与nums2中的元素(作为value)放入哈希表中

    ​ 否则将元素压栈(num一定进栈)

  2. 如果栈不为空,将元素弹栈放入哈希表中,并且value为-1

  3. 遍历nums1,将nums1中的元素在哈希表中的value遍历出来

  4. 返回接收的数组

public class Leetcode496 {
    public int[] nextGreaterElement(int[] nums1, int[] nums2) {
        int[] res = new int[nums1.length];
        Stack<Integer> stack = new Stack<>();
        HashMap<Integer, Integer> map = new HashMap<>();
        for (int num : nums2) {
        	while (!stack.isEmpty() && num > stack.peek()) {
                map.put(stack.pop(), num);
            }
            stack.push(num);
        }
        while (!stack.isEmpty()) {
            map.put(stack.pop(), -1);

        }
        for (int i = 0; i < nums1.length; i++) {
            res[i] = map.get(nums1[i]);
        }
        return res;
    }
}

这里的while写成了if导致结果错误,

while是循环语句,if是判断语句,

用 if 的话会导致漏掉一些可能性

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值