[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 用于存放values
    • Map 用于存放输入的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 items;
    private Map itemToLocation;
        
    /** Initialize your data structure here. */
    public RandomizedSet() {
        items = new ArrayList();
        itemToLocation = new HashMap();
    }
    
    /** 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();
 */

你可能感兴趣的:([Leetcode 380] Insert Delete GetRandom O(1))