题目描述:
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 elements are allowed.
insert(val)
: Inserts an item val to the collection.remove(val)
: Removes an item val from the collection if present.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();
题目大意:
设计一个数据结构支持在O(1)时间内完成如下操作:
注意:允许重复元素。
insert(val): 如果集合中不包含val,则插入val
remove(val): 如果集合中包含val,则移除val
getRandom: 从现有集合中随机返回一个元素,每个元素被返回的概率应该与其在集合中的数量线性相关。
解题思路:
本题是LeetCode 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()));
}
}
/**
* Your RandomizedCollection object will be instantiated and called as such:
* RandomizedCollection obj = new RandomizedCollection();
* boolean param_1 = obj.insert(val);
* boolean param_2 = obj.remove(val);
* int param_3 = obj.getRandom();
*/
本文链接:http://bookshadow.com/weblog/2016/08/09/leetcode-insert-delete-getrandom-o1-duplicates-allowed/
请尊重作者的劳动成果,转载请注明出处!书影博客保留对文章的所有权利。
书影网友 发布于 2017年6月12日 11:11 #
个人觉得不应该用TreeSet, TreeSet是有序的,因此每次插入时候需要消耗n*log2(n)的时间复杂度。在数据较大时,利用TreeSet不满足题目所要求的O(1)的时间复杂度
Qian 发布于 2019年7月30日 15:31 #
TreeSet 的搜索删除添加time complexity 都是O(logn)。 应该用hashset比较好