leetcode解题: Insert Delete GetRandom O(1) (380)

Design a data structure that supports all following operations in average O(1) time.

insert(val): Inserts an item val to the set if not already present.
remove(val): Removes an item val from the set if present.
getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
Example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
// Init an empty set.
RandomizedSet randomSet = new RandomizedSet();
// Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomSet.insert(1);
// Returns false as 2 does not exist in the set.
randomSet.remove(2);
// Inserts 2 to the set, returns true. Set now contains [1,2].
randomSet.insert(2);
// getRandom should return either 1 or 2 randomly.
randomSet.getRandom();
// Removes 1 from the set, returns true. Set now contains [2].
randomSet.remove(1);
// 2 was already in the set, so return false.
randomSet.insert(2);
// Since 2 is the only number in the set, getRandom always return 2.
randomSet.getRandom();

解法1:Two HashMaps

这题如果没有getRandom的话用一个set就可以解决了。因为加上了getRandom,那么需要用一些方法来存储每一个数字对应的index。由此就想到用两个hashmap来存储数字和他位置的对应关系。insert比较好解决,就是把对应关系加入两个map中。remove稍微复杂一点,首先将对应的数字pair从两个map中移除。
如果说移除的是最后一个元素或者是唯一一个元素,移除之后不需要对map额外处理。如果是移除的当中的某个元素。那么移除之后他们的index就不是连续的了。这个时候就要额外的来处理一下。因为要把最后一位的元素对应的位置-1, 那么我们可以把最后一位元素对应的位置放到刚才删除的元素的位置上。然后更新存储位置的hashmap就可以了。
Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
public class RandomizedSet {
private Map<Integer, Integer> valueIndex;
private Map<Integer, Integer> indexValue;
private Random rand;
/** Initialize your data structure here. */
public RandomizedSet() {
valueIndex = new HashMap<Integer, Integer>();
indexValue = new HashMap<Integer, Integer>();
rand = new Random(System.currentTimeMillis());
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if (valueIndex.containsKey(val)) {
return false;
} else {
int index = valueIndex.size();
valueIndex.put(val, index);
indexValue.put(index, val);
return true;
}
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if (valueIndex.containsKey(val)) {
int index = valueIndex.get(val);
valueIndex.remove(val);
indexValue.remove(index);
if (valueIndex.isEmpty() || index == valueIndex.size()) {
return true;
}
// if delete from the middle,
// put the last element into the middle
int last = indexValue.get(indexValue.size());
valueIndex.put(last, index);
indexValue.remove(indexValue.size());
indexValue.put(index, last);
return true;
} else {
return false;
}
}
/** Get a random element from the set. */
public int getRandom() {
if (valueIndex.isEmpty()) {
return -1;
} else if (valueIndex.size() == 1) {
return indexValue.get(0);
} else {
int index = rand.nextInt(valueIndex.size());
return indexValue.get(index);
}
}
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet obj = new RandomizedSet();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/