题目
设计一种结构,在该结构中有如下三个功能:
- insert(key):将某个key加入到该结构,做到不重复加入。
- delete(key):将原本在结构中的某个key移除。
- getRandom(): 等概率随机返回结构中的任何一个key。
【要求】 Insert、delete和getRandom方法的时间复杂度都是 O(1)
思路
由于要求时间复杂度为0(1),因此考虑使用HashMap
;
- 申明两个hashmap进行存储,分别对应map1、map2,同时维护一个size表示大小;
- insert方法,往map1中以<Key,Size>形式插入,往map2中以<Size,Key>形式插入
- getRandom方法时,利用Math.random函数随机取【0~size】上一个下标,返回map2中对应的K;
- delete方法时,将map1、map2 【size-1】位置数据移动到Key位置后,将尾端数据删除,保证数据连续性,避免出现空洞,导致getRandom时不等概率;
代码实现
public class RandomPool<K> {
private HashMap<K, Integer> keyToIndexMap;
private HashMap<Integer, K> indexToKeyMap;
private int size;
public RandomPool() {
keyToIndexMap = new HashMap<>();
indexToKeyMap = new HashMap<>();
size = 0;
}
/**
* 插入方法
*
* @param key
*/
public void insert(K key) {
if (keyToIndexMap.containsKey(key)) {
return;
}
keyToIndexMap.put(key, size);
indexToKeyMap.put(size, key);
size++;
}
/**
* 随机返回
*/
public K getRandom() {
if (size == 0) {
return null;
}
int index = (int) (Math.random() * size);
return indexToKeyMap.get(index);
}
/**
* 删除方法
*/
public void delete(K key) {
if (!keyToIndexMap.containsKey(key)) {
return;
}
//将最后位置的key交换到删除位置的key,移除最后位置key,保证index连续
int deleteIndex = keyToIndexMap.get(key);
int lastIndex = --size;
K lastKey = indexToKeyMap.get(lastIndex);
keyToIndexMap.put(lastKey, deleteIndex);
indexToKeyMap.put(deleteIndex, lastKey);
keyToIndexMap.remove(key);
indexToKeyMap.remove(lastIndex);
}
测试用例
public static void main(String[] args) {
RandomPool<String> randomPool = new RandomPool<>();
randomPool.insert("C");
randomPool.insert("Q");
randomPool.insert("X");
System.out.println(randomPool.getRandom());
System.out.println(randomPool.getRandom());
System.out.println(randomPool.getRandom());
System.out.println("----------------------");
randomPool.delete("Q");
System.out.println(randomPool.getRandom());
System.out.println(randomPool.getRandom());
System.out.println(randomPool.getRandom());
}