问题:
设计数据结构,使得以下三个方法的时间复杂度都为O(1)
允许插入重复数字。
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();
解法:
本题需让insert,remove的复杂度为O(1)
数组的insert方法复杂度满足,remove中的查找不满足,因此加入hash来帮助记录消化查找的代价。
另,由于允许可重复的数字,那么再使hash中的value为一个数组,记录同一个数字的不同位置
vector<int, int> nums //fisrt: 插入数值,second:该数字在map中,同一个数字数组中存的位置 i1
unordered_map<int, vector<int>> //(key: nums[i], value: [i1,i2,i3...])
代码参考:
1 class RandomizedCollection { 2 public: 3 /** Initialize your data structure here. */ 4 RandomizedCollection() { 5 6 } 7 8 /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */ 9 bool insert(int val) { 10 11 if(mapnums.find(val)==mapnums.end()){ 12 mapnums[val].push_back(nums.size()); 13 nums.push_back({val,0}); 14 }else{ 15 vector<int>* tmp = &mapnums[val]; 16 tmp->push_back(nums.size()); 17 nums.push_back({val,tmp->size()-1}); 18 } 19 return true; 20 } 21 22 /** Removes a value from the collection. Returns true if the collection contained the specified element. */ 23 bool remove(int val) { 24 if(mapnums.find(val)==mapnums.end()) return false; 25 pair<int,int> last = nums.back(); 26 int indexval = mapnums[val].back(); 27 nums[indexval]=last; 28 mapnums[last.first][last.second]=indexval; 29 mapnums[val].pop_back(); 30 if(mapnums[val].empty()){ 31 mapnums.erase(val); 32 } 33 nums.pop_back(); 34 return true; 35 } 36 37 /** Get a random element from the collection. */ 38 int getRandom() { 39 return nums[rand() % nums.size()].first; 40 } 41 private: 42 vector<pair<int, int>> nums; 43 unordered_map<int,vector<int>> mapnums; 44 }; 45 46 /** 47 * Your RandomizedCollection object will be instantiated and called as such: 48 * RandomizedCollection* obj = new RandomizedCollection(); 49 * bool param_1 = obj->insert(val); 50 * bool param_2 = obj->remove(val); 51 * int param_3 = obj->getRandom(); 52 */