双散列表实现随机概率返回

这篇博客探讨了一种数据结构设计,它支持添加String而不重复,能够严格等概率随机返回其中的元素,并且提供了删除功能,所有这些操作的时间复杂度均为O(1)。通过使用双散列表(HashMap)来实现,一个用于存储key-value,另一个用于value-key,从而确保不重复和等概率随机性。在删除操作中,通过填补空洞并更新相关映射来保持结构完整。这种方法对于高效的数据操作具有重要意义。
摘要由CSDN通过智能技术生成

题目要求

设计一个结构,实现三个功能:
1.add();
将某个String添加到该结构中,做到不重复添加。
2.getRandom();
严格等概率随机返回结构中的任何一个key。
3.delete();
要求以上三个方法的时间复杂度全部为O(1)。

思路分析

1.add()
添加String,并且要求不重复。不重复?O(1)?想到什么?散列表。
2.getRandom()
严格等概率随机返回,相当于要求随机返回散列表中的一个key。首先要知道,散列函数的散列区间并不是严格等概率分布的,要想做到严格等概率分布,怎么实现?
严格等概率分布,相当于要求统计出到底有多少个key,然后用Math.random函数就能实现严格随机。如果统计有多少个key?如果遍历key。时间复杂度就不是1了。怎么实现1?可以用map实现,value依次加1,value对应的就是统计多少个key。但是,等我们通过Math.random函数求出随机的value时,如何找到对应的key?此时,可以考虑用双散列表实现。两个散列表的key和value依次对调
map1保存key-value(String,int)
map2保存value-key(int,String)
用map1保证key不会重复,然后用map2实现等概率随机。
3.delete()
删除方法,给定一个String,删除掉。
不过,有一个问题,等我们删除掉一个时,map中间就会出现一个空洞,此时再调用第二部的随机方法,就会出现问题。
因此,删除方法要能填补中间的空洞。可以先把最后一个复制到空洞处,然后删除最后一个。
map1中,把最后一个的value改成要删除的那个,此时最后一个和要删除的value相同,然后删除。
map2中,把要删除的num的value替换掉,然后删除最后一个。
最后。size–。

代码

import java.util.HashMap;

public class RandomPool {

    private HashMap<String,Integer> map1;
    private HashMap<Integer,String> map2;
    private int size;

    public RandomPool(){
        map1=new HashMap<>();
        map2=new HashMap<>();
        size=0;
    }

    public void add(String str){
        map1.put(str,size);
        map2.put(size,str);
        size++;
    }

    public String getRandom(){
        if(size==0){
            return null;
        }
        return map2.get((int)(Math.random()*size));
    }

    public void delete(String string){
        //获取要删除的num
        int num=map1.get(string);
        //获取最后一个
        String last = map2.get(size);
        //把最后一个复制到num的位置,此时有两个num
        map1.put(last,num);
        //删除string
        map1.remove(string);
        //替换到num位置的string,此时有两个last
        map2.put(num,last);
        //删除掉最后一个
        map2.remove(size);
        size--;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值