380. Insert Delete GetRandom O(1)

来源:互联网 发布:全天时时彩计划数据 编辑:程序博客网 时间:2024/06/05 08:27


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),注意这里的平均,即题目中的average,并非exactly。这样就能使用HashMap了。看了这道题的Discuss,Discuss里的争论焦点在于能否使用HashMap,要知道,当插入数据遇到冲突时,HashMap的时间复杂度可能降至O(n)。目前主流的观点是,一般情况下HashMap的插入和删除的时间复杂度为O(1),只有当我们遇到散列冲突时,才需要详细分析HashMap时间复杂度。只要能用HashMap,在插入和删除时,我们就可以在O(1)的复杂度下,迅速判断出HashMap内是否包含某个key的键值对。

随机读取元素需要用到类似数组的存储结构,Java中类似的容器是ArrayList。有一个问题需要注意,ArrayList在删除元素时,需要把删除位置后面的元素,依次向前覆盖,最差情况下,时间复杂度降至O(n)。只有在删除最后一个元素时,因为不用移动元素,复杂度为O(1)。因此在删除ArrayList中的某个元素时,可以用最后一个元素替换当前元素,然后删除最后一个元素即可。(当然,此时ArrayList中元素的顺序也发生了变化,最后一个元素被前移了,不过对于本题来讲无所谓,见下图)

这里写图片描述

import java.util.HashMap;import java.util.ArrayList;import java.util.Random;public class RandomizedSet {    ArrayList<Integer> arr;    HashMap<Integer, Integer> map;    Random rand;    /** Initialize your data structure here. */    public RandomizedSet() {        arr = new ArrayList<Integer>();        map = new HashMap<Integer, Integer>();        rand = new Random();    }    /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */    public boolean insert(int val) {        boolean contain = map.containsKey(val);        if(!contain) {            map.put(val, arr.size());            arr.add(val);        }        return !contain;    }    /** Removes a value from the set. Returns true if the set contained the specified element. */    public boolean remove(int val) {        boolean contain = map.containsKey(val);        if(contain) {            int index = map.get(val);            int lastIndex = arr.size() - 1;            Integer lastEle = arr.get(lastIndex);            arr.set(index, lastEle);            map.put(lastEle, index);            arr.remove(lastIndex);            map.remove(val);        }        return contain;    }    /** Get a random element from the set. */    public int getRandom() {        int index = rand.nextInt(arr.size());        return arr.get(index);    }}/** * 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(); */
0 0
原创粉丝点击