本文主要是介绍【C++】每日一题 380 O(1)时间插入,删除和获取随机元素,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!
实现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 <cstdlib>class RandomizedSet {
private:std::unordered_map<int, int> valToIndex; // 用于存储值到索引的映射std::vector<int> 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 映射的正确性。
这篇关于【C++】每日一题 380 O(1)时间插入,删除和获取随机元素的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!