954. Insert Delete GetRandom O(1) - Duplicates allowed

Description

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

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

Example 1:

Input:

insert(1)

insert(1)

insert(2)

getRandom()

remove(1)

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

Example 2:

Input:

insert(1)

insert(1)

getRandom()

remove(1)

思路:

和没有重复的那个题思路类似,但是因为允许有重复数字,所以hash_map中用List存储了所有一样val的index,注意函数defaultdict对于任何一个遍历到的val都会有一个默认的空set,所以再remove的时候要去判断self.index[val]是不是空,而不能用not in self.index。另外删除一个val的时候并没有真正的删除,而是将list中那个val替换成了None,所以在生成随机数的时候,要排除掉那些为None的值。

用 HashMap 存储 number to a list of indices in numbers array. 也就是说,把某个数在数组中出现的所有的位置用 List 的形式存储下来

这样子的话,删除一个数的时候,就是从这个 list 里随便拿走一个数(比如最后一个数)

但是还需要解决的问题是,原来的算法中,删除一个数的时候,需要拿 number array 的最后个位置的数,来覆盖掉被删除的数。那这样原本在最后一个位置的数,他在 HashMap 里的记录就应该相应的变化。

但是,我们只能得到这个移动了的数是什么,而这个被移动过的数,可能出现在好多个位置上,去要从 HashMap 里得到的 indices 列表里,改掉那个 index=当前最后一个位置的下标。

所以这里的做法是,修改 number array,不只是存储 Number,同时存储,这个数在 HashMap 的 indices 列表中是第几个数。这样就能直接去改那个数的值了。否则还得 for 循环一次,就无法做到 O(1)

代码


你可能感兴趣的:(954. Insert Delete GetRandom O(1) - Duplicates allowed)