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:
// 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()
思路
For inserting and deleting, we need to check if a value exists before in O(1) time. Consider hash table.
-
For getting random the array is a good choice because:
- Get every number with same possibility
- Get number in O(1) time
-
因此该data structure需要2个数据结构来支撑:
-
ArrayList<Integer>
用于存放values -
Map <Integer, Integer>
用于存放输入的value的值和value在ArrayList中的位置的mapping
key
: value的值。value
: Value在ArrayList中的index
Example:
-
items : (value/ index)
[ 1 ] `0`
[ 0 ] `1`
[ 4 ] `2`
Mapping: (value/ index in items array)
<1, 0>
<0, 1>
<4, 2>
-
Insert operation:
- Check if mapping contains current val, only insert if it doesn't contain
1)向arraylist中加入val。
2) 将该val和array list的size - 1
作为mapping set加入hash table。(因为insert的时候都是加入到arraylist的尾部, 所以size - 1
就是当前val在arraylist中的index)
- Check if mapping contains current val, only insert if it doesn't contain
-
remove operation:
- Check if mapping contains current val, only remove if it doesn't contain
- 题目并未要求保持顺序,而且要求remove的time complexity为1, 所以不能直接从中间remove, 这样会导致所有其后面的元素都需要顺序移位。
solution => Array List中将最后一个item replace 掉需要被remove的item,然后delete掉最后一个item。这样就能在 **O(1) **时间内完成remove - 除了需要从Array List中移除item,还需要update hash table。
- 用remove item在Array List中的index,替代hash table中 移除item之前 array list里last item的index。 (因为,array list 中last item会与remove item交换位置,从而其location index就是remove item 的location)
- 再从Hash Table中remove掉val所在的map entry set
- 题目并未要求保持顺序,而且要求remove的time complexity为1, 所以不能直接从中间remove, 这样会导致所有其后面的元素都需要顺序移位。
- Check if mapping contains current val, only remove if it doesn't contain
注意 :因为需要用到Array List中last item index, 所以在真正从array list中移除item之前,先更新hash table,再更新array list
-
Random Operation
用Random object在【0,ArrayList.size()】范围内生成一个随机int,用于array list的随机获取指针
Code
class RandomizedSet {
private List<Integer> items;
private Map<Integer, Integer> itemToLocation;
/** Initialize your data structure here. */
public RandomizedSet() {
items = new ArrayList<Integer>();
itemToLocation = new HashMap<Integer, Integer>();
}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
public boolean insert(int val) {
if (itemToLocation.containsKey(val))
{
return false;
}
itemToLocation.put(val, items.size());
items.add(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
public boolean remove(int val) {
if (!itemToLocation.containsKey(val))
{
return false;
}
// update hashtable
int lastItem = items.get (items.size() - 1);
int itemToRemoveLocation = itemToLocation.get(val);
itemToLocation.put (lastItem, itemToRemoveLocation);
itemToLocation.remove (val);
// update arraylist: swap val and last item, and then remove the last item from the array list
items.set (itemToRemoveLocation, lastItem);
items.remove (items.size() - 1);
return true;
}
/** Get a random element from the set. */
public int getRandom() {
Random random = new Random ();
int ranEleIndx = random.nextInt (items.size ());
return items.get(ranEleIndx);
}
}
/**
* 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();
*/