Using ArrayList's get function to implement getRandom() in constant time, and a hashmap to save the <Value, Index> pair.
So we need to make sure the index of the last element always equals to the size of the list - 1.
When we delete an element from the the list, we don't directly delete it, however, replace it with the last element in the list, and update the index in the hash map for this new added element.
If the insert operation allow duplicate element, add a HashSet to record the indices for duplicate elements. The map would be <Value, HashSet>.
public class RandomizedSet {
HashMap<Integer, Integer> map; // A hashtable to save <Value, Index> pair so that allows getRandom() in constant time
List<Integer> list; // A list to allow insert and remove operations
Random rand;
/** Initialize your data structure here. */
public RandomizedSet() {
map = new HashMap<Integer, Integer>();
list = new ArrayList<Integer>(); // size, get, set all in constant time for ArrayList
rand = new Random();
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if (map.containsKey(val)) {
return false;
}
list.add(val);
map.put(val, list.size()-1);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
// Remove element from both map and list
if (!map.containsKey(val)) {
return false;
}
int index = map.get(val);
int last = list.get(list.size()-1);
list.set(index, last); // replace the element with last element in the list
list.remove(list.size()-1); // remove the element from list
map.put(last, index); // update the index for the last element
map.remove(val); // remove the element from map
return true;
}
/** Get a random element from the set. */
public int getRandom() {
return list.get(rand.nextInt(list.size())); // return a random position from 0 to list.size()-1
}
}