380 Insert Delete GetRandom O(1) 常数时间插入、删除和获取随机元素
Description:
Implement the RandomizedSet class:
bool insert(int val) Inserts an item val into the set if not present. Returns true if the item was not present, false otherwise.
bool remove(int val) Removes an item val from the set if present. Returns true if the item was present, false otherwise.
int getRandom() Returns a random element from the current set of elements (it's guaranteed that at least one element exists when this method is called). Each element must have the same probability of being returned.
Follow up: Could you implement the functions of the class with each function works in average O(1) time?
Example:
Example 1:
Input
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]
Explanation
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomizedSet.remove(2); // Returns false as 2 does not exist in the set.
randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.
randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].
randomizedSet.insert(2); // 2 was already in the set, so return false.
randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.
Constraints:
-2^31 <= val <= 2^31 - 1
At most 105 calls will be made to insert, remove, and getRandom.
There will be at least one element in the data structure when getRandom is called.
题目描述:
设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。
insert(val):当元素 val 不存在时,向集合中插入该项。
remove(val):元素 val 存在时,从集合中移除该项。
getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。
示例 :
// 初始化一个空的集合。
RandomizedSet randomSet = new RandomizedSet();
// 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomSet.insert(1);
// 返回 false ,表示集合中不存在 2 。
randomSet.remove(2);
// 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomSet.insert(2);
// getRandom 应随机返回 1 或 2 。
randomSet.getRandom();
// 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomSet.remove(1);
// 2 已在集合中,所以返回 false 。
randomSet.insert(2);
// 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
randomSet.getRandom();
思路:
使用 map记录值和下标
使用 vector(列表)记录值
插入时如果有重复值, 返回 false, 否则存入 map和插在列表的结尾, 返回 true
移除时如果查找 map中没有, 返回 false, 否则将列表的最后一个元素和待删除的元素交换, 更新 map对应的下标, 移除 map和列表的最后一个元素, 返回true
获取一个随机数, 范围为列表的长度值
insert()时间复杂度O(1), remove()时间复杂度O(1), getRandom()时间复杂度O(1), 空间复杂度O(n)
代码:
C++:
class RandomizedSet
{
public:
/** Initialize your data structure here. */
RandomizedSet() {}
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
bool insert(int val)
{
if (m.count(val)) return false;
m[val] = v.size();
v.emplace_back(val);
return true;
}
/** Removes a value from the set. Returns true if the set contained the specified element. */
bool remove(int val)
{
if (!m.count(val)) return false;
int i = m[val], last = v.back();
v[i] = last;
m[last] = i;
v.pop_back();
m.erase(m.find(val));
return true;
}
/** Get a random element from the set. */
int getRandom()
{
return v[rand() % v.size()];
}
private:
vector v;
unordered_map m;
};
/**
* Your RandomizedSet object will be instantiated and called as such:
* RandomizedSet* obj = new RandomizedSet();
* bool param_1 = obj->insert(val);
* bool param_2 = obj->remove(val);
* int param_3 = obj->getRandom();
*/
Java:
class RandomizedSet {
private List list;
private Map map;
private Random random;
/** Initialize your data structure here. */
public RandomizedSet() {
list = new ArrayList<>();
map = new HashMap<>();
random = 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;
map.put(val, list.size());
list.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 (!map.containsKey(val)) return false;
int i = map.get(val), last = list.get(list.size() - 1);
list.set(i, last);
list.remove(list.size() - 1);
map.put(last, i);
map.remove(val);
return true;
}
/** Get a random element from the set. */
public int getRandom() {
return list.get(random.nextInt(list.size()));
}
}
/**
* 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();
*/
Python:
class RandomizedSet:
def __init__(self):
"""
Initialize your data structure here.
"""
self.hash_table = {}
self.stack = []
def insert(self, val: int) -> bool:
"""
Inserts a value to the set. Returns true if the set did not already contain the specified element.
"""
if val in self.hash_table:
return False
self.hash_table[val] = len(self.stack)
self.stack.append(val)
return True
def remove(self, val: int) -> bool:
"""
Removes a value from the set. Returns true if the set contained the specified element.
"""
if val not in self.hash_table:
return False
i, last = self.hash_table[val], self.stack[-1]
self.stack[i] = last
self.hash_table[last] = i
del self.hash_table[val]
del self.stack[-1]
return True
def getRandom(self) -> int:
"""
Get a random element from the set.
"""
return self.stack[random.randint(0, len(self.stack) - 1)]
# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()