题意
同380 - Insert Delete GetRandom O(1),只不过支持重复元素。
思路
pre
我们先考虑还是用unordered_map+vector来做,既然支持重复元素,那么我们可以将重复元素穿成一条链,即unordered_map的结构为unordered_map<int, vector<int>> has,其中vector存储的为对应在arr里的下标。
insert(val):has[val].push_back(), O(1)getRandom():arr[rand() % size], O(1)remove(val): 取has[val]对应vector的最后一个元素的位置pos,并且将arr[]最后一个位置lastPos上的元素x放到pos上达到删除的目的,并且需要修改has[x]的映射关系:我们会发现,我们需要在has[x]里面先找到vector里面存储的下标为lastPos的位置,然后修改成pos,时间复杂度会上升到O(n)。
now
所以,需要修改我们的数据结构。
既然,导致我们时间复杂度上升到O(n)的操作是在has[x]对应的vector里面去遍历找到对应值为lastPos对应的位置并修改,那么我们能否直接在arr[]里面存储lastPos在has[x]的vector里面对应的位置呢?
显然我们可以将arr[]的数据结构修改为vector<pair<int, int>> arr。
其中,arr[pos].first代表当前位置pos存储的元素值val,arr[pos].second代表当前位置存储的元素值val在has[val]连接的vector里面出现的位置。
假设我们依次插入:
1, 2, 1, 1, 4, 4, 3
那么,表示为:
代码
class RandomizedCollection {
private:
unordered_map<int, vector<int>> has;
vector<pair<int, int>> arr;
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) {
auto flag = (has.find(val) == has.end());
has[val].push_back(arr.size());
arr.push_back(make_pair(val, has[val].size() - 1));
return flag;
}
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
auto flag = (has.find(val) != has.end());
if (flag) {
int pos = has[val].back();
auto last = arr.back();
arr[pos] = last;
has[last.first][last.second] = pos;
has[val].pop_back();
arr.pop_back();
if (has[val].empty()) has.erase(val);
}
return flag;
}
/** Get a random element from the collection. */
int getRandom() {
return arr[rand() % arr.size()].first;
}
};
/**
* 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();
* **/

本文介绍了一种支持重复元素的随机集合数据结构实现方法。利用unordered_map和vector组合,通过跟踪每个元素及其在数组中的位置,实现了高效的插入、删除及随机获取操作。
807

被折叠的 条评论
为什么被折叠?



