1. 程式人生 > >[leetcode]381. Insert Delete GetRandom O(1) - Duplicates allowed

[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.

 

  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();

題目

 

思路

 

程式碼

 1 class RandomizedCollection {
 2                      // TreeSet用來處理每個相同val的不同idx
 3     HashMap<Integer, TreeSet<Integer>> map;
 4     List<Integer> list;
 5     Random random;
 6     /** Initialize your data structure here. */
 7     public RandomizedCollection() {
8 map = new HashMap<>(); 9 list = new ArrayList<>(); 10 random = new Random(); 11 } 12 13 /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ 14 public boolean insert(int val) { 15 TreeSet<Integer> idxSet = map.get(val); 16 // 如果該val不在map裡,則先扔到map裡一對新pair 17 if (idxSet == null) { 18 idxSet = new TreeSet<>(); 19 map.put(val, idxSet); 20 } 21 //如果該val在map裡,則給該val分配一個新idx,記錄在idxSet中 22 // list.size() 這個操作的是O(1)的,原始碼可查 23 idxSet.add(list.size()); 24 list.add(val); 25 //if the collection did not already contain,則新加一個idx後 idxSet.size() 為1 26 // if the collection already contain,則新加一個idx後 idxSet.size() >1 27 return idxSet.size() == 1; 28 } 29 30 /** Removes a value from the collection. Returns true if the collection contained the specified element. */ 31 public boolean remove(int val) { 32 TreeSet<Integer> idxSet = map.get(val); // val(20) : idxSet(0-3-6) 33 // corner case 34 if (idxSet == null || idxSet.isEmpty()) { 35 return false; 36 } 37 // removeIdx可以在idxSet找任意idex,pollLast()只是方便起見 38 int removeIdx = idxSet.pollLast(); 39 int replaceVal = list.get(list.size() - 1); //Tail of list 40 // 因為允許duplicates, 這個TreeSet裡裝著所有replaceVal對應的不同idx 41 TreeSet<Integer> tailIdxSet = map.get(replaceVal); 42 if (replaceVal != val) { 43 tailIdxSet.pollLast(); //Remove last removeIdx of list replaceVal 44 tailIdxSet.add(removeIdx); //Add removeIdx to replaceVal removeIdx set 45 list.set(removeIdx, replaceVal); 46 } 47 list.remove(list.size() - 1); 48 return true; 49 } 50 51 /** Get a random element from the collection. */ 52 public int getRandom() { 53 return list.get(random.nextInt(list.size())); 54 } 55 }