Insert Delete GetRandom O(1) 系列
380. Insert Delete GetRandom O(1)
介绍
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();
解答
使用一个unordered_map和vector来进行数据的存储。
vector用于实际的数据存储,unordered_map中存储着数据和vector中相应的下标。
insert(val)
: 先在unordered_map中查找val,查找成功则返回false。否则则直接在vector的最后添加val,并在unordered_map中添加映射关系。remove(val)
:先在unordered_map中查找val,查找失败则返回false。否则,先在unordered_map确定val在vector的下标值,然后将vector的最后一个元素换到这个位置,然后删除最后一个元素,同时需要注意更新mapping中的映射关系,并删除相应元素。- 对vector的大小做模,然后取相应元素。
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(mapping.find(val) != mapping.end()) return false;
mapping[val] = nums.size();
nums.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(mapping.find(val) == mapping.end()) return false;
int last = nums.size()-1;
int cur = mapping[val];
mapping[nums[last]] = cur;
nums[cur] = nums[last];
nums.pop_back();
mapping.erase(val);
return true;
}
/** Get a random element from the set. */
int getRandom() {
return (nums[rand()%nums.size()]);
}
vector<int> nums;
unordered_map<int,int> mapping;
};
/**
* 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();
*/
381. Insert Delete GetRandom O(1) - Duplicates allowed
介绍
Design a data structure that supports all following operations in average O(1) time.
Note: 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.
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();
题意: 本题比上题目的难度要稍大,主要是因为允许重复元素的插入。
解答
本题中依然采取一个unordered_map
class RandomizedCollection {
public:
/** Initialize your data structure here. */
RandomizedCollection() {
}
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
bool insert(int val) {
bool res;
unordered_map<int,vector<int>>::iterator it = mapping.find(val);
if(it == mapping.end() || it->second.empty()) //collection中不存在元素val
{
nums.emplace_back(val,0);
mapping[val].emplace_back(nums.size()-1);
res = true;
}else
{
nums.emplace_back(val,it->second.size());
it->second.emplace_back(nums.size()-1);
res = false;
}
return res;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
unordered_map<int,vector<int>>::iterator it = mapping.find(val);
if(it == mapping.end() || it->second.empty()) return false;
int cur = it->second.back();
int last = nums.size()-1;
nums[cur] = nums[last];
it->second.pop_back();
nums.pop_back();
unordered_map<int,vector<int>>::iterator it_last = mapping.find(nums[cur].first);
it_last->second[nums[cur].second] = cur;
return true;
}
/** Get a random element from the collection. */
int getRandom() {
return (nums[rand()%nums.size()].first);
}
vector<pair<int,int>> nums;
unordered_map<int,vector<int>> mapping;
};
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* bool param_1 = obj.insert(val);
* bool param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/