java_hashmap_get_random()

【问题】

设计一个类似hashmap的结构,
3个功能 
insert(key):将某个key加入到该结构,做到不重复,
delete(key):将原本在结构中的某个key去除
getRandom():等概率随机返回结构中的任何一个key
要求:
3个功能时间复杂度为O(1), 不能遍历

【原理】

----- 借用2个Hashmap,

第一个Hashmap:Str, index

第二个Hashmap:index, Str

----- Delete函数:

为了保证,等概率返回,必须保证0~size中间没有空缺,这才能保证Math.random()等概率找到的index内部有值,

如果每次,不把最后一行的值,填补在删除了那一行,0~size上面就不会有空缺。

【代码】

// 做一个结构,类似哈希表,3个功能,但是有要求,参见Hashmap_random_01

import java.util.HashMap;

public class Hashmap_random_02 {
	// 使用泛型
//	Java中泛型的两个主要好处是:
//  它与java中的泛型有关。如果我提到ArrayList<String>这意味着我只能向该ArrayList添加字符串类型对象。
//	减少程序中的强制转换数,从而减少程序中潜在的错误数。
//	提高代码清晰度
	public static class RandomPool<K>{
		private HashMap<K, Integer> map1; // Hashmap1, 第一列是外部输入的字符串,第二列是计数用的Integer
		private HashMap<Integer, K> map2; // Hashmap2, 第一列是外部输入的Integer,第二列是计数用的字符串
		public int size;
		// 初始化
		public RandomPool() {
			this.map1 = new HashMap<K, Integer>();
			this.map2 = new HashMap<Integer, K>();
			size = 0;
		}
		
		// insert函数 
		public void insert(K key) {
			// 1) 分别在map1,与map2中放入新的String与对应的index),size++
			if (!this.map1.containsKey(key)) {  // 如果当前Hashmap1中不包含需要放进去的String,判断条件
				this.map1.put(key, this.size);
				this.map2.put(this.size++, key); //  把size++ 集合写了
			}
		}
		
		// delete函数
		public void delete(K key) {
			if (this.map1.containsKey(key)) { //如果需要删除的(字符串)在Hashmap1中
				// 1)获取需要删除的哪一行的index
				int deleteIndex = this.map1.get(key); 
				// 2)获取最后一个行,index 与 值
				int lastIndex = --this.size; 
				K lastKey = this.map2.get(lastIndex); // 获取最后一行的值,通过哈希表2,String 字符串
				// 3)把最后一行的key与value,放到需要删除的那一行,进行替换
				this.map1.put(lastKey, deleteIndex); //在此映射中关联指定值与指定键。如果此映射以前包含了一个该键的映射关系,则旧值被替换。
				this.map2.put(deleteIndex, lastKey);
				// 4)删除原来的key&与对应的value,删除最后一行的值与values
				this.map1.remove(key); // 删除Hashmap1 最后一行
				this.map2.remove(lastIndex); //删除 Hashmap2 最后一行
			}
		}
	
		// getRandom函数,随机取返回一个东西(不考虑删除的情况,0~size中间中间有洞)
		public K getRandom() {
			if (size == 0) {
				return null;
			}
			int index = (int)(Math.random()*size); //0~size上是无序的,但是要保证中间没洞
			return this.map2.get(index);
		}
		
	}
	

	public static void main(String[] args) {
		RandomPool<String>  pool = new RandomPool<>();
		pool.insert("Liu");
		pool.insert("Ha");
		pool.insert("XX");
		
		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());
		
	}

}

猜你喜欢

转载自blog.csdn.net/sinat_15355869/article/details/82314107