Insert Delete GetRandom O(1) - Duplicates allowed
Design a data structure that supports all following operations in average O(1) time.
Example
// Init an empty collection.
RandomizedCollection collection = new RandomizedCollection();
// Inserts 1 to the collection. Returns true as the collection did not contain 1.
collection.insert(1);
// Inserts another 1 to the collection. Returns false as the collection contained 1. Collection now contains [1,1].
collection.insert(1);
// Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
collection.insert(2);
// getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
collection.getRandom();
// Removes 1 from the collection, returns true. Collection now contains [1,2].
collection.remove(1);
// getRandom should return 1 and 2 both equally likely.
collection.getRandom();
Notice
Duplicate elements are allowed.
insert(val): Inserts an item val to the collection.
remove(val): Removes an item val from the collection if present.
getRandom: Returns a random element from current collection of elements. The probability of each element being returned is linearly related to the number of same value the collection contains.
解法
思路1
- 在I的基础上允许duplicate
- 还是用的I的思想
- 这种题不在乎时间复杂度的其实非常简单,要求O(1)的话,需要对数据结构做一些改变
- 在I的基础上直接做,那么久需要维护一个val -> list of values, 如果只是一个val -> 次数,那么无法找到对应的list中的位置,无法在O(1)进行getRandom
- 最开始想使用HashMap
- 这样能通过value找到了这个value对应的index list,但是使用List又需要O(k)时间遍历,
- 所以想到了HashMap
> - value -> a map(list) of nodes, in the map, index -> value
- 这样我们可以通过O(1)完成对这个双重map的操作
- 每次remove的时候都会对这个双重map进行操作,而且都是O(1)
思路2
- 其实跟思路1差不多
- 变成linkedlist with HashMap 或者 linkedHashMap
- 有head和tail节点进行删除,增加
- 代码
class RandomizedCollection {
/** Initialize your data structure here. */
// value -> a map(list) of nodes, in the map, index -> value
Map<Integer, Map<Integer, Integer>> value_map;
Map<Integer, Integer> index_map;
List<Integer> list;
Random rand;
public RandomizedCollection() {
value_map = new HashMap<Integer, Map<Integer, Integer>>();
index_map = new HashMap<Integer, Integer>();
list = new ArrayList<Integer>();
rand = new Random();
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
public boolean insert(int val) {
// write your code here
Map<Integer, Integer> map = null;
if (value_map.containsKey(val)) {
map = value_map.get(val);
} else {
map = new HashMap<Integer, Integer>();
}
list.add(val);
map.put(list.size() - 1, val);
value_map.put(val, map);
index_map.put(list.size() - 1, val);
return true;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
public boolean remove(int val) {
// write your code here
if (!value_map.containsKey(val)) {
return false;
}
Map<Integer, Integer> map = value_map.get(val);
if (map.size() == 0) {
return false;
}
Iterator iterator = map.entrySet().iterator();
Map.Entry pair = (Map.Entry)iterator.next();
int index = (Integer)pair.getKey();
map.remove(index);
index_map.remove(index);
int last_value = list.get(list.size() - 1);
if (last_value == val) {
list.remove(list.size() - 1);
return true;
}
int last_index = list.size() - 1;
swap(list, index, last_index);
list.remove(list.size() - 1);
index_map.remove(last_index);
index_map.put(index, last_value);
Map<Integer, Integer> map_of_last = value_map.get(last_value);
map_of_last.remove(last_index);
map_of_last.put(index, last_value);
return true;
}
public void swap(List<Integer> list, int index1, int index2) {
int temp = list.get(index1);
list.set(index1, list.get(index2));
list.set(index2, temp);
}
/** Get a random element from the collection. */
public int getRandom() {
// write your code here
return list.get(rand.nextInt(list.size()));
}
}
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/