Design a data structure that supports all following operations in average O(1) time.

Note: Duplicate elements are allowed.

  1. insert(val): Inserts an item val to the collection.
  2. remove(val): Removes an item val from the collection if present.
  3. getRandom: Returns a random element from current collection of elements. The probability of each element being returned is linearly related to the number of same value the collection contains.

Example:

// Init an empty collection.
RandomizedCollection collection = new RandomizedCollection(); // Inserts 1 to the collection. Returns true as the collection did not contain 1.
collection.insert(1); // Inserts another 1 to the collection. Returns false as the collection contained 1. Collection now contains [1,1].
collection.insert(1); // Inserts 2 to the collection, returns true. Collection now contains [1,1,2].
collection.insert(2); // getRandom should return 1 with the probability 2/3, and returns 2 with the probability 1/3.
collection.getRandom(); // Removes 1 from the collection, returns true. Collection now contains [1,2].
collection.remove(1); // getRandom should return 1 and 2 both equally likely.
collection.getRandom();

380. Insert Delete GetRandom O(1)的拓展,这题是可以有重复数字。只需将上一题目的解法稍作改动,依然使用哈希表+数组,这次哈希表中的值是保存数组下标的一个Set。

Java:

import java.util.ArrayList;
import java.util.HashMap;
import java.util.Random;
import java.util.TreeSet; public class RandomizedCollection { private HashMap<Integer, TreeSet<Integer>> dataMap;
private ArrayList<Integer> dataList;
/** Initialize your data structure here. */
public RandomizedCollection() {
dataMap = new HashMap<Integer, TreeSet<Integer>>();
dataList = new ArrayList<Integer>();
} /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
public boolean insert(int val) {
TreeSet<Integer> idxSet = dataMap.get(val);
if (idxSet == null) {
idxSet = new TreeSet<Integer>();
dataMap.put(val, idxSet);
}
idxSet.add(dataList.size());
dataList.add(val);
return idxSet.size() == 1;
} /** Removes a value from the collection. Returns true if the collection contained the specified element. */
public boolean remove(int val) {
TreeSet<Integer> idxSet = dataMap.get(val);
if (idxSet == null || idxSet.isEmpty()) {
return false;
}
int idx = idxSet.pollLast(); //Last index of val
int tail = dataList.get(dataList.size() - 1); //Tail of list
TreeSet<Integer> tailIdxSet = dataMap.get(tail);
if (tail != val) {
tailIdxSet.pollLast(); //Remove last idx of list tail
tailIdxSet.add(idx); //Add idx to tail idx set
dataList.set(idx, tail);
}
dataList.remove(dataList.size() - 1);
return true;
} /** Get a random element from the collection. */
public int getRandom() {
return dataList.get(new Random().nextInt(dataList.size()));
}
}

Python:

from random import randint
from collections import defaultdict class RandomizedCollection(object): def __init__(self):
"""
Initialize your data structure here.
"""
self.__list = []
self.__used = defaultdict(list) def insert(self, val):
"""
Inserts a value to the collection. Returns true if the collection did not already contain the specified element.
:type val: int
:rtype: bool
"""
has = val in self.__used self.__list += val,
self.__used[val] += len(self.__list)-1, return not has def remove(self, val):
"""
Removes a value from the collection. Returns true if the collection contained the specified element.
:type val: int
:rtype: bool
"""
if val not in self.__used:
return False self.__used[self.__list[-1]][-1] = self.__used[val][-1]
self.__list[self.__used[val][-1]], self.__list[-1] = self.__list[-1], self.__list[self.__used[val][-1]] self.__used[val].pop()
if not self.__used[val]:
self.__used.pop(val)
self.__list.pop() return True def getRandom(self):
"""
Get a random element from the collection.
:rtype: int
"""
return self.__list[randint(0, len(self.__list)-1)]

C++:

class RandomizedCollection {
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) {
m[val].insert(nums.size());
nums.push_back(val);
return m[val].size() == 1;
} /** Removes a value from the collection. Returns true if the collection contained the specified element. */
bool remove(int val) {
if (m[val].empty()) return false;
int idx = *m[val].begin();
m[val].erase(idx);
if (nums.size() - 1 != idx) {
int t = nums.back();
nums[idx] = t;
m[t].erase(nums.size() - 1);
m[t].insert(idx);
}
nums.pop_back();
return true;
} /** Get a random element from the collection. */
int getRandom() {
return nums[rand() % nums.size()];
} private:
vector<int> nums;
unordered_map<int, unordered_set<int>> m;
};

  

类似题目:

[LeetCode] 380. Insert Delete GetRandom O(1) 插入删除获得随机数O(1)时间

All LeetCode Questions List 题目汇总

[LeetCode] 381. Insert Delete GetRandom O(1) - Duplicates allowed 插入删除和获得随机数O(1)时间 - 允许重复的更多相关文章

  1. [LeetCode] 380. Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

  2. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed O(1) 时间插入、删除和获取随机元素 - 允许重复(C++/Java)

    题目: Design a data structure that supports all following operations in averageO(1) time. Note: Duplic ...

  3. [LeetCode] 381. Insert Delete GetRandom O(1) - Duplicates allowed 常数时间内插入删除和获得随机数 - 允许重复

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  4. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed

    原题链接在这里:https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/?tab=Description ...

  5. LeetCode 381. Insert Delete GetRandom O(1) - Duplicates allowed (插入删除和获得随机数 常数时间 允许重复项)

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  6. [leetcode]381. Insert Delete GetRandom O(1) - Duplicates allowed常数时间插入删除取随机值

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  7. leetcode 380. Insert Delete GetRandom O(1) 、381. Insert Delete GetRandom O(1) - Duplicates allowed

    380. Insert Delete GetRandom O(1) 实现插入.删除.获得随机数功能,且时间复杂度都在O(1).实际上在插入.删除两个功能中都包含了查找功能,当然查找也必须是O(1). ...

  8. 381. Insert Delete GetRandom O(1) - Duplicates allowed

    Design a data structure that supports all following operations in average O(1) time. Note: Duplicate ...

  9. [LeetCode] Insert Delete GetRandom O(1) 常数时间内插入删除和获得随机数

    Design a data structure that supports all following operations in average O(1) time. insert(val): In ...

随机推荐

  1. uiautomator2+python自动化测试2-查看app页面元素利器weditor

    前言 android sdk里面自带的uiautomatorviewer.bat可以查看手机app上的元素,但是不太好用,网上找了个大牛写的weditor,试用了下还是蛮不错的 python环境:3. ...

  2. AD-logon workstation

    默认AD登录到限制为64个 原因 发生此问题的原因是User-Workstations属性的Range-Upper值为1,024个字符.使用Active Directory用户和计算机输入NetBIO ...

  3. zookeeper 的 docker 镜像使用

    dockerhub 网址:https://hub.docker.com/_/zookeeper

  4. 使用postman开发testcases记录贴

    我使用了两个版本的postman: Postman-linux-x64-7.1.1 这是目前(2019)最新版本.这个版本也有坑: (因为系统崩溃重装了,所以目前只有最新版本.本文截图都是这个版本的截 ...

  5. Python中实现count(distinct )

    假设一个表有6个字段c1,c2,c3,c4,c5,c6,有如下的sql语句: select c1,count(distinct(c6)) from tbl where c3>1 group by ...

  6. 如何使用keil5将stm32的hal库编译成lib文件——F1版本

    hal库中keil5中编译的速度是比较慢的,相同情况下,每次都要编译的时候,比标准库是要慢很多的,因此就hal库编译成lib文件是一种加快编译速度的方法,当然也有其自身的缺点.一.步骤1.使用cube ...

  7. TypeScript语言学习笔记(3)函数,泛型

    函数 // 具名函数和匿名函数 // Named function function add(x, y) { return x + y; } // Anonymous function let myA ...

  8. UVa11542Squre——异或方程组&&高斯消元法

    题意 给出 $n$ 个整数,从中选出1个或多个,使得选出的整数乘积是完全平方数.一共有多少种选法?($1 \leq n \leq 100$,$1 \leq a_i \leq 10^{15}$ 且不含大 ...

  9. Redis存储List

    list中数据可以重复,查询快,增删慢. 存储结构: 1.向List存取数据: 查询list中的全部元素: 第一个进入a,第二个进入b,并将a向后移一位. 上图为从右边插入元素的情况. 2.从两头取出 ...

  10. CSS文本元素

    一.属性 font-size:16px;  文字大小 Font-weight: 700 ;   值从100-900,文字粗细,不推荐使用font-weight:bold; Font-family:微软 ...