[Leetcode 380] Insert Delete GetRandom O(1)

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

思路

  1. For inserting and deleting, we need to check if a value exists before in O(1) time. Consider hash table.

  2. For getting random the array is a good choice because:

    • Get every number with same possibility
    • Get number in O(1) time
  3. 因此该data structure需要2个数据结构来支撑:

    • ArrayList<Integer> 用于存放values
    • Map <Integer, Integer>用于存放输入的value的值和value在ArrayList中的位置的mapping
      key: value的值。 value: Value在ArrayList中的index

    Example

  items : (value/ index)  
       [ 1 ]  `0`                               
       [ 0 ]  `1`
       [ 4 ]  `2`
 Mapping: (value/ index in items array)
      <1, 0>
      <0, 1>
      <4, 2>
  1. Insert operation

    • Check if mapping contains current val, only insert if it doesn't contain
      1)向arraylist中加入val。
      2) 将该val和array list的size - 1作为mapping set加入hash table。(因为insert的时候都是加入到arraylist的尾部, 所以size - 1就是当前val在arraylist中的index)
  2. remove operation

    • Check if mapping contains current val, only remove if it doesn't contain
      1. 题目并未要求保持顺序,而且要求remove的time complexity为1, 所以不能直接从中间remove, 这样会导致所有其后面的元素都需要顺序移位。
        solution => Array List中将最后一个item replace 掉需要被remove的item,然后delete掉最后一个item。这样就能在 **O(1) **时间内完成remove
      2. 除了需要从Array List中移除item,还需要update hash table。
        • 用remove item在Array List中的index,替代hash table中 移除item之前 array list里last item的index。 (因为,array list 中last item会与remove item交换位置,从而其location index就是remove item 的location)
        • 再从Hash Table中remove掉val所在的map entry set

注意 :因为需要用到Array List中last item index, 所以在真正从array list中移除item之前,先更新hash table,再更新array list

  1. Random Operation
    用Random object在【0,ArrayList.size()】范围内生成一个随机int,用于array list的随机获取指针

Code

class RandomizedSet {

    private List<Integer> items;
    private Map<Integer, Integer> itemToLocation;
        
    /** Initialize your data structure here. */
    public RandomizedSet() {
        items = new ArrayList<Integer>();
        itemToLocation = 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 (itemToLocation.containsKey(val))
        {
            return false;
        }
        
        itemToLocation.put(val, items.size());
        items.add(val);
        return true;
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    public boolean remove(int val) {
        if (!itemToLocation.containsKey(val))
        {
            return false;
        }
        
        // update hashtable
        int lastItem = items.get (items.size() - 1);
        int itemToRemoveLocation = itemToLocation.get(val);
        itemToLocation.put (lastItem, itemToRemoveLocation);
        itemToLocation.remove (val);
        
        // update arraylist: swap val and last item, and then remove the last item from the array list
        items.set (itemToRemoveLocation, lastItem);
        items.remove (items.size() - 1);
        
        return true;
    }
    
    /** Get a random element from the set. */
    public int getRandom() {
        Random random = new Random ();
        int ranEleIndx = random.nextInt (items.size ());
        return items.get(ranEleIndx);
    }
}

/**
 * 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();
 */
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,445评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,889评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,047评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,760评论 1 276
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,745评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,638评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,011评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,669评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,923评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,655评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,740评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,406评论 4 320
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,995评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,961评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,197评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,023评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,483评论 2 342

推荐阅读更多精彩内容

  • pyspark.sql模块 模块上下文 Spark SQL和DataFrames的重要类: pyspark.sql...
    mpro阅读 9,443评论 0 13
  • Lua 5.1 参考手册 by Roberto Ierusalimschy, Luiz Henrique de F...
    苏黎九歌阅读 13,729评论 0 38
  • 背景 一年多以前我在知乎上答了有关LeetCode的问题, 分享了一些自己做题目的经验。 张土汪:刷leetcod...
    土汪阅读 12,719评论 0 33
  • 空白的颜色 是炽热的灯泡 发着暗黄的光 被筛成黑白色调 空白的气味 是冰箱里的剩菜 在低温下隔开味蕾 空白的时间 ...
    空蛹满梦阅读 121评论 0 0
  • 1、今天,社会调查老师上课,提到自己任课、调研一年多没有好好看本书了,顺口问我们什么情况,一片寂静……随即说我们趁...
    晨沐阅读 323评论 0 2