Leetcode 381 - Insert Delete GetRandom O(1) - Duplicates allowed

24 篇文章 0 订阅
8 篇文章 0 订阅

题意

同380 - Insert Delete GetRandom O(1),只不过支持重复元素。

思路

pre

我们先考虑还是用unordered_map+vector来做,既然支持重复元素,那么我们可以将重复元素穿成一条链,即unordered_map的结构为unordered_map<int, vector<int>> has,其中vector存储的为对应在arr里的下标。

  1. insert(val): has[val].push_back(), O(1)
  2. getRandom(): arr[rand() % size], O(1)
  3. remove(val): 取has[val]对应vector的最后一个元素的位置pos,并且将arr[]最后一个位置lastPos上的元素x放到pos上达到删除的目的,并且需要修改has[x]的映射关系:我们会发现,我们需要在has[x]里面先找到vector里面存储的下标为lastPos的位置,然后修改成pos,时间复杂度会上升到 O(n)
now

所以,需要修改我们的数据结构。

既然,导致我们时间复杂度上升到 O(n) 的操作是在has[x]对应的vector里面去遍历找到对应值为lastPos对应的位置并修改,那么我们能否直接在arr[]里面存储lastPoshas[x]vector里面对应的位置呢?

显然我们可以将arr[]的数据结构修改为vector<pair<int, int>> arr

其中,arr[pos].first代表当前位置pos存储的元素值valarr[pos].second代表当前位置存储的元素值valhas[val]连接的vector里面出现的位置。

假设我们依次插入:

1, 2, 1, 1, 4, 4, 3

那么,表示为:
这里写图片描述

代码

class RandomizedCollection {
private:
    unordered_map<int, vector<int>> has;
    vector<pair<int, int>> arr;

public:
    /** Initialize your data structure here. */
    RandomizedCollection() {
    }

    /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
    bool insert(int val) {
        auto flag = (has.find(val) == has.end());
        has[val].push_back(arr.size());
        arr.push_back(make_pair(val, has[val].size() - 1));
        return flag;
    }

    /** Removes a value from the collection. Returns true if the collection contained the specified element. */
    bool remove(int val) {
        auto flag = (has.find(val) != has.end()); 
        if (flag) {
            int pos = has[val].back();
            auto last = arr.back();
            arr[pos] = last;
            has[last.first][last.second] = pos;
            has[val].pop_back();
            arr.pop_back();
            if (has[val].empty()) has.erase(val);
        }
        return flag;
    }

    /** Get a random element from the collection. */
    int getRandom() {
        return arr[rand() % arr.size()].first; 
    }
};

/**
 * Your RandomizedCollection object will be instantiated and called as such:
 * RandomizedCollection obj = new RandomizedCollection();
 * bool param_1 = obj.insert(val);
 * bool param_2 = obj.remove(val);
 * int param_3 = obj.getRandom();
 * **/
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值