flash网站大全,微信搜索推广,春节网页设计素材,学习吧网站实现RandomizedSet 类#xff1a;
RandomizedSet() 初始化 RandomizedSet 对象 bool insert(int val) 当元素 val 不存在时#xff0c;向集合中插入该项#xff0c;并返回 true #xff1b;否则#xff0c;返回 false 。 bool remove(int val) 当元素 val 存在时#xf…实现RandomizedSet 类
RandomizedSet() 初始化 RandomizedSet 对象 bool insert(int val) 当元素 val 不存在时向集合中插入该项并返回 true 否则返回 false 。 bool remove(int val) 当元素 val 存在时从集合中移除该项并返回 true 否则返回 false 。 int getRandom() 随机返回现有集合中的一项测试用例保证调用此方法时集合中至少存在一个元素。每个元素应该有 相同的概率 被返回。 你必须实现类的所有函数并满足每个函数的 平均 时间复杂度为 O(1) 。
#include unordered_map
#include vector
#include cstdlibclass RandomizedSet {
private:std::unordered_mapint, int valToIndex; // 用于存储值到索引的映射std::vectorint values; // 用于存储集合中的值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 (valToIndex.find(val) ! valToIndex.end()) {return false; // 如果值已经存在则返回false}values.push_back(val); // 在向量末尾插入新值valToIndex[val] values.size() - 1; // 更新值到索引的映射return true;}/** Removes a value from the set. Returns true if the set contained the specified element. */bool remove(int val) {if (valToIndex.find(val) valToIndex.end()) {return false; // 如果值不存在则返回false}int index valToIndex[val]; // 获取值在向量中的索引int lastVal values.back(); // 获取向量中最后一个值values[index] lastVal; // 将最后一个值移到被删除的位置valToIndex[lastVal] index; // 更新最后一个值的索引values.pop_back(); // 删除最后一个值valToIndex.erase(val); // 删除值到索引的映射return true;}/** Get a random element from the set. */int getRandom() {int randomIndex rand() % values.size(); // 生成随机索引return values[randomIndex]; // 返回随机索引处的值}
};
使用了一个 unordered_map 来存储值到索引的映射以实现 O(1) 时间复杂度的插入和删除操作。同时使用一个 vector 来存储集合中的值并且通过将被删除元素与最后一个元素交换然后再删除最后一个元素的方式来实现 O(1) 时间复杂度的删除操作。最后getRandom 函数通过生成一个随机索引来随机返回集合中的一个元素。
易错点 从 nums 向量中删除特定值 val 对应的元素并且更新 indices 映射使得其仍然与 nums 同步。以下代码错误示范
nums.erase(nums.begin()indices[val]);
indices.erase(val);假设 indices[val] 给出了 val 在 nums 中的索引位置。第一行代码是从 nums 向量中删除这个索引位置的元素但是删除后后面的元素会向前移动填补被删除的位置这就会导致原来在 indices[val] 位置的元素变成了新的 val而且 val 在 nums 中的位置已经改变了所以删除 val 对应的索引值并不正确。
正确的做法是通过交换最后一个元素和要删除的元素来实现删除然后更新映射。这就是下面的代码片段
int index indices[val];
int last nums.back();
nums[index] last;
indices[last] index;
nums.pop_back();
indices.erase(val);这样做的好处是它避免了在删除元素后重新排序 nums 向量同时保持了 indices 映射的正确性。