插入 删除 获取随机数 O(1) - C++ 中允许重复

c++server side programmingprogramming更新于 2025/6/25 21:22:17

假设我们要创建一个数据结构,该结构支持某些操作,这些操作必须在 O(1) 的时间内完成。因此,让这些操作类似于 −

  • insert(x):将 x 插入集合
  • remove(x):从集合中删除 x
  • getRandom():这将从该集合中查找随机元素。

为了解决这个问题,我们将遵循以下步骤 −

  • 创建一个数组 nums
  • 创建一个映射 m
  • 定义一个函数 insert(),该函数接受 val
  • 当 val 不在 m 中时,ret :=
  • 在 m[val] 的末尾插入 nums 的大小
  • insert { val, m[val] 的大小 – nums 末尾的 1} 对
  • 返回 ret
  • 定义一个函数 remove(),该函数接受 val
  • 当 val 不在 m 中时,ret :=
  • 如果 ret 非零,则减去
    • last = nums 的最后一个元素
    • m[last 的键][last 的值] := m[val] 的最后一个元素
    • nums[[m[val]] 的最后一个元素 := last
    • 从 m[val] 中删除最后一个元素
    • 如果 m[val] 为空,则减去
      • 从 m 中删除 val
    • 从 nums 中删除最后一个元素
  • 返回ret
  • 定义一个函数 getRandom()
  • 从集合中返回一个随机元素

让我们看看下面的实现以便更好地理解 −

示例

#include <bits/stdc++.h>
using namespace std;
class RandomizedCollection {
public:
   vector <pair <int, int>> nums;
   unordered_map <int, vector<int>> m;
   RandomizedCollection() {
   }
   bool insert(int val) {
      bool ret = m.find(val) == m.end();
      m[val].push_back(nums.size());
      nums.push_back({val, m[val].size() - 1});
      return ret;
   }
   bool remove(int val) {
      bool ret = m.find(val) != m.end();
      if(ret){
         pair <int, int> last = nums.back();
         m[last.first][last.second] = m[val].back();
         nums[m[val].back()] = last;
         m[val].pop_back();
         if(m[val].empty())m.erase(val);
         nums.pop_back();
      }
      return ret;
   }
   int getRandom() {
      return nums[rand() % nums.size()].first;
   }
};
main(){
   RandomizedCollection ob;
   ob.insert(10);
   ob.insert(35);
   ob.insert(20);
   ob.insert(40);
   cout << (ob.getRandom()) << endl;
   ob.remove(20);
   cout << (ob.getRandom()) << endl;
}

输入

Insert 10, 35, 20, 40, then get one random number, say 40, then remove 20, again get random element, that is say 35.

输出

40
35

相关文章