• [LeetCode] 381. Insert Delete GetRandom O(1)


    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 题目汇总

  • 相关阅读:
    第33周二
    第33周一
    第32周日
    第32周六
    RichTextBox 右键显示 ContextMenuTrip
    关于 Head First SQL 中文版
    linux进程通信之共享内存
    chroot 与 jail
    SQL基础--&gt; 约束(CONSTRAINT)
    MessageDigest简单介绍
  • 原文地址:https://www.cnblogs.com/lightwindy/p/8512239.html
Copyright © 2020-2023  润新知