【LeetCode每日一题打卡】380. O(1) 时间插入、删除和获取随机元素

204 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第3天,点击查看活动详情

LeetCode每日一题打卡专栏正式启动!不出意外将日更LeetCode的每日一题,敬请期待。

个人博客链接:bbstudy.net/ (等毕业论文做好后续会完善相关功能)

4.13:O(1) 时间插入、删除和获取随机元素

LeetCode 380,点击题目可直接跳转至LeetCode

题解:哈希表

对于获取随机元素,数组可以在O(1)时间做到,但是对于插入和删除操作,数组却无能为力。

对于插入和删除操作,哈希表可以在O(1)时间做到,但是对于获取随机元素操作,哈希表却又不可奈何。

于是思考:能否将两者结合,实现O(1)时间:插入、删除和获取随机元素。

  • 用一可变数组num:存储集合中的元素
  • 哈希表中:key存储num中的元素,value存储对应的索引

当执行插入操作(插入元素在集合中未出现)时:

  1. num数组直接在末尾添加
  2. 哈希表则把插入的元素和对应的末尾下标存入其中

当执行删除操作(待删除元素在集合中)时:

  1. 将num数组中末尾元素移动至当前需要删除元素的索引处
  2. 在哈希表中更新num数组中末尾对应的value值(即索引)
  3. num数组删除最后一个元素,哈希表删除待删除的元素

借此巩固下Java集合类的使用,于是提供C++和Java代码:

C++代码:

class RandomizedSet {
public:
    unordered_map<int,int> mp;   //key->num,value->index
    vector<int>  num;
    RandomizedSet() {
        mp.clear();num.clear();
        srand(time(0));   //随机数种子
    }
    
    bool insert(int val) {
        if(mp.count(val)) return false;
        num.push_back(val);
        mp[val]=num.size()-1;
        return true;
    }
    
    bool remove(int val) {
        if(!mp.count(val)) return false;
        //将num数组中最后一个元素填入到此位置
        int index=mp[val];
        int x=num.back();
        mp[x]=index;
        num[index]=x;
        //在num数组中删除最后一个元素,同时mp中也删除需要删除的元素
        num.pop_back();mp.erase(val);
        return true;
    }
    
    int getRandom() {
        int pos=rand()%num.size();
        return num[pos];
    }
};
​
/**
 * Your RandomizedSet object will be instantiated and called as such:
 * RandomizedSet* obj = new RandomizedSet();
 * bool param_1 = obj->insert(val);
 * bool param_2 = obj->remove(val);
 * int param_3 = obj->getRandom();
 */

Java代码:

class RandomizedSet {
    Map<Integer,Integer> map;
    List<Integer> num;
    public RandomizedSet() {
        map=new HashMap<Integer,Integer>();
        num=new ArrayList<>();
    }
    
    public boolean insert(int val) {
        if(map.containsKey(val)) return false;
        num.add(val);
        map.put(val,num.size()-1);
        return true;
    }
    
    public boolean remove(int val) {
        if(!map.containsKey(val)) return false;
        //将num最后一个元素移动至当前位置
        int index=map.get(val);
        int last=num.get(num.size()-1);
        num.set(index,last);
        map.put(last,index);
        //删除num最后一个元素,删除map中需要删除的元素
        num.remove(num.size()-1);
        map.remove(val);
        return true;
    }
    
    public int getRandom() {
        Random rand=new Random();
        int index=rand.nextInt(num.size());
        return num.get(index);
    }
}