设计一个可以支持O(1)时间复杂度以下操作的数据结构。
- insert(x):在数据结构中插入x。如果x不存在,则返回True;如果x已经存在,则返回False。
- remove(x):从数据结构中删除x(如果存在)。
- getRandom():随机返回流中存在的任何值。返回每个元素的概率应与流中包含的相同值元素的数量成线性比例。
方法:在上一篇文章中,我们已经讨论了用于这种数据结构的方法。但是,以前的数据结构仅适用于唯一值。在本文中,我们将设计一个可以处理重复元素的数据结构。
本文使用的方法与以前的方法非常相似,但是为了处理重复的元素,使用了一组映射来存储动态数组中存在的元素的索引。让我们独立地了解每种方法。
- insert(int x):
- 在动态数组nums []的末尾插入x。
- 将x(即nums.size()– 1)的索引插入mp [x] 。该集合映射存储动态数组nums []中存在的元素x的所有索引。
- 删除(int x):
- 通过mp.count(x)检查流中是否存在x。如果不存在,则返回False 。
- 如果存在x,则删除集合mp [x]的第一个元素,并将其值存储在变量indexRemoved中。现在,如果该元素(即indexRemoved)与nums.length()相同,则直接转到步骤6,因为这意味着该元素已经位于最后一个索引,并且该元素将在恒定时间内删除。
- 如果不是,则为了在恒定时间内删除此元素,该元素将与动态数组中的最后一个元素交换。因此,从mp [nums [nums.size()– 1]]集中删除值nums.size()– 1。
- 将值索引插入mp [nums [nums.size()– 1]]集。
- 交换索引为nums.size()– 1和indexRemoved为nums的元素。
- 从nums中删除最后一个元素(从Dynamic Array的末尾删除是恒定时间操作)。
- 如果mp [val]设置为空,则从mp删除val。
- 返回真
- getRandom():
- 获取介于0和nums.size()– 1之间的随机数。
- 返回此数字索引处的值。
下面是上述方法的实现:
// C++ program to design a data structure
// that supports insert, delete,
// getRandom in O(1) with duplicates
#include
using namespace std;
class Stream {
private:
// Stores all the numbers present
// currently in the stream
vector nums;
// Unordered ensure O(1) operation
unordered_map > mp;
public:
// Function to insert values
// in the stream
bool insert(int val)
{
// Inserting val to the end of array
nums.push_back(val);
// Index at which val was inserted
int index = nums.size() - 1;
// Inserting the index inside the
// set mp[val]
mp[val].insert(index);
// Return True if only one val
// is present in the stream
return mp[val].size() == 1;
}
// Function to remove the value
// from the stream
bool remove(int val)
{
// If the value is not present
// in the stream
if (!mp.count(val))
return 0;
// Get the value of the first element
// of the mp[val] and store it
// in a variable named index
int index = *(mp[val].begin());
// Last Index of nums
int lastIndex = nums.size() - 1;
// Erase the index from mp[val] set
mp[val].erase(index);
// If index == lastIndex, then the
// element was already deleted
// from the stream
if (index != lastIndex) {
// Delete the lastIndex from
// mp[nums[lastIndex]] set
mp[nums[lastIndex]].erase(lastIndex);
// Insert index into mp[nums[lastIndex]] set
mp[nums[lastIndex]].insert(index);
// Swap the values at index and lastIndex
swap(nums[index], nums[lastIndex]);
}
// Delete the last element from nums
// This operation is O(1) operation
nums.pop_back();
// If the size of mp[val] is 0,
// val is absent from the stream
// and hence it is removed
if (mp[val].size() == 0)
mp.erase(val);
return 1;
}
// Function to get a random number
// from the stream of data
int getRandom()
{
// Get any random index from 0 to
// nums.length() - 1
int randomIndex = rand() % nums.size();
// Return the value at that index
return nums[randomIndex];
}
};
// Driver code
int main()
{
Stream myStream;
cout << myStream.insert(5) << endl;
cout << myStream.insert(6) << endl;
cout << myStream.insert(5) << endl;
cout << myStream.remove(6) << endl;
cout << myStream.remove(6) << endl;
cout << myStream.getRandom() << endl;
return 0;
}
输出:
1
1
0
1
0
5