zoukankan      html  css  js  c++  java
  • leetcode380- Insert Delete GetRandom O(1)- medium

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

    1. insert(val): Inserts an item val to the set if not already present.
    2. remove(val): Removes an item val from the set if present.
    3. getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.

    Example:

    // Init an empty set.
    RandomizedSet randomSet = new RandomizedSet();
    
    // Inserts 1 to the set. Returns true as 1 was inserted successfully.
    randomSet.insert(1);
    
    // Returns false as 2 does not exist in the set.
    randomSet.remove(2);
    
    // Inserts 2 to the set, returns true. Set now contains [1,2].
    randomSet.insert(2);
    
    // getRandom should return either 1 or 2 randomly.
    randomSet.getRandom();
    
    // Removes 1 from the set, returns true. Set now contains [2].
    randomSet.remove(1);
    
    // 2 was already in the set, so return false.
    randomSet.insert(2);
    
    // Since 2 is the only number in the set, getRandom always return 2.
    randomSet.getRandom();

    性能这么好肯定是得空间换时间。加删都是O(1),想到要用到Hash,但是HashSet不能random存取,所以想到用HashMap。如果要随机获得的话需要把对象聚在一起不能有分散

    1.List + Map + size。amortized O(1)。Map一直记录 obj-index对。删的时候有额外小技巧,list的任意删是O(n)的,但是如果你一直都只删最后一个对象那还是O(1)的,所以你要做的就是把最后一个数和要删的互换,然后删最后的就好了。

    2.两个Map + size。真的O(1)。一个Map记录obj-index对,一个Map记录index-obj对。删的时候也是需要换最后一个。(细节:remove的时候Map操作一定要先更新put再remove最后一个,反过来的话当只有一个元素的时候删就会出问题,刚删完又回来了)。

    细节:几个函数:list.set(int index, Obj obj); map.remove(K key); new Random().nextInt(int bound);

    1. List + Map

    class RandomizedSet {
        
        private int size;
        private List<Integer> list;
        private Map<Integer, Integer> map;
        /** Initialize your data structure here. */
        public RandomizedSet() {
            list = new ArrayList<Integer>();
            map = new HashMap<Integer, Integer>();
        }
        
        /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
        public boolean insert(int val) {
            if (map.containsKey(val)) {
                return false;
            }
            list.add(size,val);
            map.put(val, size);
            size++;
            return true;
        }
        
        /** Removes a value from the set. Returns true if the set contained the specified element. */
        public boolean remove(int val) {
            if (!map.containsKey(val)) {
                return false;
            }
            int idx = map.get(val);
            int temp = list.get(size - 1);
            list.set(idx, temp);
            map.put(temp, idx);
            map.remove(val);
            // 记得要切实地把最后一个东西挪掉,因为你add的时候选择直接add,那你会把东西加到垃圾后面
            list.remove(--size);
            return true;
        }
        
        /** Get a random element from the set. */
        public int getRandom() {
            Random rdm = new Random();
            return list.get(rdm.nextInt(size));
        }
    }
    
    /**
     * Your RandomizedSet object will be instantiated and called as such:
     * RandomizedSet obj = new RandomizedSet();
     * boolean param_1 = obj.insert(val);
     * boolean param_2 = obj.remove(val);
     * int param_3 = obj.getRandom();
     */

    2. Map + Map

    class RandomizedSet {
        
        Map<Integer, Integer> vi;
        Map<Integer, Integer> iv;
        int size;
        /** Initialize your data structure here. */
        public RandomizedSet() {
            vi = new HashMap<Integer, Integer>();
            iv = new HashMap<Integer, Integer>();
            size = 0;
        }
        
        /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
        public boolean insert(int val) {
            if (vi.containsKey(val)) {
                return false;
            }
            vi.put(val, size);
            iv.put(size, val);
            size++;
            return true;
        }
        
        /** Removes a value from the set. Returns true if the set contained the specified element. */
        public boolean remove(int val) {
            if (!vi.containsKey(val)) {
                return false;
            }
            int index = vi.get(val);
            int lastVal = iv.get(size - 1);
            // 千万小心这里put和remove不能换位置,为了避免只有一个条目的情况,你先删再加的话就把原来的东西加回去了。
            vi.put(lastVal, index);
            vi.remove(val);
            iv.put(index, lastVal);
            iv.remove(size - 1);
            size--;
            return true;
        }
        
        /** Get a random element from the set. */
        public int getRandom() {
            return iv.get(new Random().nextInt(size));
        }
    }
    
    /**
     * Your RandomizedSet object will be instantiated and called as such:
     * RandomizedSet obj = new RandomizedSet();
     * boolean param_1 = obj.insert(val);
     * boolean param_2 = obj.remove(val);
     * int param_3 = obj.getRandom();
     */
  • 相关阅读:
    支持向量机 (三): 优化方法与支持向量回归
    支持向量机 (二): 软间隔 svm 与 核函数
    支持向量机 (一): 线性可分类 svm
    拉格朗日乘子法
    特征选择: 卡方检验、F 检验和互信息
    Python 多进程、多线程效率比较
    Umi+Dva搭建Cesium 3D开发环境
    React 项目生产版本迭代页面不刷新问题
    React-Native学习手册----搭建基于ios平台的开发环境
    Cesium 绘制点、线、面和测距
  • 原文地址:https://www.cnblogs.com/jasminemzy/p/7940561.html
Copyright © 2011-2022 走看看