哈希1:认识哈希函数和哈希表;设计RandomPool结构

Hash函数特点:
1.输入域无穷,输出域有限。例如:有无穷多个(在工程中可以具体到多少个,例如1000)输入参数经过hash函数映射后得到有限的输出域{1,2,3,4}。
2.输入参数确定,经过hash函数映射出的返回值一样。(不是随机函数,不同的输入参数可能得到相同的返回值)。
3.输入域上的值经过函数值映射后会几乎均等的分布在输出域上。 得到的输出值%m,也会均匀分布在0–m上。
具体了解哈希函数和哈希表可以参考这篇文章:请点击这里

补充:hashmap里面的结构原理是什么,key通过hash函数得到一个hashcode,然后决定放入到数组的那个位置里面,map中的key,value是以Entry的形式存在数组里面的,同一个hashcode的值会存入同一个位置里面,在jdk1.7里面是使用链表的方式将同一个hashcode的值相互连接。jdk1.8里面是使用数组+链表+红黑树。具体详细可以参考这个文章:请点击这里
我们可以认为hash表的增删改查的复杂度都是O(1)的。

【题目】 设计一种结构,在该结构中有如下三个功能: insert(key):将某个key加入到该结构,做到不重复加入。 delete(key):将原本在结构中的某个key移除。 getRandom(): 等概率随机返回结构中的任何一个key。 【要求】 Insert、delete和getRandom方法的时间复杂度都是 O(1)
思想:这道题,我们可以使用两个hashmap来完成,一个用来存放(key,size),一个用来存放(size,key)。insert方法,如果不包含key,则两个hashmap都存放进去;delete方法,首先,我们通过(key,size)这个hashmap查看是否存在,然后因为删除了那么这个map里面肯定是有一个空洞的,所有我们可以先把要删除的那个Key放到最后的一个位置,然后再删除它,size–。
为什么要用两个map呢,思考一下,因为当我们删除的时候我们不仅仅要得到要删除的那个key,我们还要知道最后的那个key,这样我们才能把最后的那个key放到删除的那个位置去。

在这里插入图片描述
代码:



import java.util.HashMap;

public class Code_02_RandomPool {

	public static class Pool<K> { //定义一个这样的pool结构
		private HashMap<K, Integer> keyIndexMap;
		private HashMap<Integer, K> indexKeyMap;
		private int size;

		public Pool() {
			this.keyIndexMap = new HashMap<K, Integer>();
			this.indexKeyMap = new HashMap<Integer, K>();
			this.size = 0;
		}

		public void insert(K key) {
			if (!this.keyIndexMap.containsKey(key)) {
				this.keyIndexMap.put(key, this.size);
				this.indexKeyMap.put(this.size++, key);
			}
		}

		public void delete(K key) {
			if (this.keyIndexMap.containsKey(key)) {
				int deleteIndex = this.keyIndexMap.get(key);//得到要删除的那个key的下标value
				int lastIndex = --this.size; //删除后,size减一
				K lastKey = this.indexKeyMap.get(lastIndex);//得到最后的那个key
				this.keyIndexMap.put(lastKey, deleteIndex);//把最后的那个key放到要删除的那个位置上
				this.indexKeyMap.put(deleteIndex, lastKey);//一样,把最后的那个位置放到要删除的那个位置
				this.keyIndexMap.remove(key);
				this.indexKeyMap.remove(lastIndex);
			}
		}

		public K getRandom() {
			if (this.size == 0) {
				return null;
			}
			int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1 乘以size会得到一个一个0-size的整数
			return this.indexKeyMap.get(randomIndex);
		}

	}

	public static void main(String[] args) {
		Pool<String> pool = new Pool<String>();
		pool.insert("hh");
		pool.insert("baby");
		pool.insert("xixi");
		System.out.println(pool.getRandom());
		System.out.println(pool.getRandom());
		System.out.println(pool.getRandom());
		System.out.println(pool.getRandom());
		System.out.println(pool.getRandom());
		System.out.println(pool.getRandom());

	}

}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值