左神算法:RandomPool

本文介绍了一种特殊的数据结构,能够实现insert、delete和getRandom三种操作的时间复杂度均为O(1)。通过巧妙的设计,利用两个哈希表分别存储key到index和index到key的映射,以及一个技巧性的删除策略,确保了数据的均匀分布和随机访问的等概率性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目:
设计一种结构,在该结构中有如下三个功能:
insert(key):将某个key加入到该结构,做到不重复加入。
delete(key):将原本在结构中的某个key移除。
getRandom(): 等概率随机返回结构中的任何一个key。
【要求】 Insert、delete和getRandom方法的时间复杂度都是 O(1)
分析:这个结构一看感觉跟哈希表的结构比较像,但是哈希表是get<key,value> 这道题只用get key还有就是一个哈希表不能严格做到等概率 时间复杂度O(1)的返回key,因为当样本量小的时候,数据做不到均匀分布,样本量多了可以看成是均匀分布,但是等概率是不可能的。所以删除有个技巧,会在代码中体现。

public static class Pool<T>{
  private HashMap<T,Integer> keyIntegerMap;
  private HashMap<Integer, T> integerKeyMap;
  
  private int size;
  
  public Pool(){
   this.keyIntegerMap = new HashMap<T, Integer>();
   this.integerKeyMap = new HashMap<Integer, T>();
   this.size = 0;
  }
  public void insert(T key) {
   if(!this.keyIntegerMap.containsKey(key)) {//做到不重复加入
    this.keyIntegerMap.put(key, this.size);
    this.integerKeyMap.put(this.size++, key);
   }
  }
  /*
   * 删除的时候,如果直接删除key那么在这个范围上会缺一个“洞”,当有1000个数据,删除了999个
   * 那么在等概率获取值的时候,生成的随机不一定会直接到最后存在的那个数据。就需要在返回生成新的随机数
   * 所以需要在删除这个地方有个技巧。在删除当前值的时候。我们把最后的一个值放在当前值的位置上,再remove最后一个值,size--就行了
   */
  public void delete(T key) {
   if(this.keyIntegerMap.containsKey(key)) {
    int deleteIndex = this.keyIntegerMap.get(key);//得到这个key的对应值,在integerKeyMap中删除
    int lastIndex = --this.size;
    T lastKey = this.integerKeyMap.get(lastIndex);
    this.integerKeyMap.put(deleteIndex, lastKey);
    this.keyIntegerMap.put(lastKey, deleteIndex);
    this.integerKeyMap.remove(deleteIndex);
    this.keyIntegerMap.remove(lastKey);
   }
  }
  //等概率的获得key,需要可以使用随机数,和已经标记的size。
  public T getRandom() {
   if (this.size == 0) {
    return null;
   }
   int randomIndex = (int) (Math.random() * this.size); // 0 ~ size -1
   return this.integerKeyMap.get(randomIndex);
  }
  }

新人第一次写博客,想要记录一下自己在学习过程中的收获。希望大家多多关照

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值