设计一个可以常数时间插入和删除的集合--设计问题

文章目录

C++实现详解

image.png


class RandomizedSet {
private:
//用一个hash表以及一个动态数组,每次插入在最后,并通过hash表记录对应的下标
//删除的时候直接与最后的数进行交换,然后pop_back()以达到常数级别的删除
    unordered_map<int,int>hash;
    vector<int>data;
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) {
        //如果已经含有该元素返回false
        if(hash.count(val))
            return false;
        data.push_back(val);
        hash[val] = data.size()-1;
        return true;
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    bool remove(int val) {
        //如果data中不存在val就不可能删除成功
        if(!hash.count(val))
            return false;
//为了得到O(1)时间的复杂度不择手段,用了偷天换日的手法(把要删除位置的值用最后一个位置的值覆盖,然后删除最后一个位置的值即可)
        //通过hash表得到它对应的下标,得到后便删除hash中的映射
        int pos = hash[val];
        //不能在这里erase,因为如果data数组只有一个元素时,一旦pop,后面又会重新创建hash,本来vector中已经没得元素了,但是hash中却又有了映射,所以erase必须在新的hash关系建立之后
        int nowVal = data.back();
        data[pos] = nowVal;
        //删除最后一个数,并且把它的下标映射更新
        data.pop_back();
        hash[nowVal] = pos;
        //最后再删除原来的映射
        hash.erase(val);
        return true;
    }
    
    /** Get a random element from the set. */
    int getRandom() {
        int size = data.size();
        int index = rand()%size;
        return data[index];
    }
};

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值