380. Insert Delete GetRandom O(1)

https://leetcode.com/problems/insert-delete-getrandom-o1/#/description

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

Sol:

import random
class RandomizedSet(object):

    def __init__(self):
        """
        Initialize your data structure here.
        """
        self.l = []
        self.d = {}

    def insert(self, val):
        """
        Inserts a value to the set. Returns true if the set did not already contain the specified element.
        :type val: int
        :rtype: bool
        """
        # insert time: O(1) for dict, O(1) for array
        if val in self.d:
            return False
        # since element is inserted one by one, the length of the list is also its index, and we store the index as the value of the dict.
        self.d[val] = len(self.l)
        self.l.append(val)
        return True

    def remove(self, val):
        """
        Removes a value from the set. Returns true if the set contained the specified element.
        :type val: int
        :rtype: bool
        """
        
        # delete time: O(1) for dict, more than O(1) for array.
        # however for array, pop out the last element is O(1). So let dict find the element to be delete and swap the "to be delete" element in the array to the end of the array. Then delete the element at the end of the array and the corresponding data in hash table/dict. 
        if val not in self.d:
            return False
        # i is the index of "to be delete" element
        i = self.d[val]
        # newVal is the last element in the list, it is going to be swapped
        newVal = self.l[-1]
        # after the swap, position i in the array now occupies the previous last element
        self.l[i] = newVal
        # dont forget to update the (key, value) pair in the dict. dict synchronizes with array.
        self.d[newVal] = i
        # finially delete the value in the dict
        del self.d[val]
        # pop off the last element in the array. we have copied the last element. array synchronizes with dict.
        self.l.pop()
        return True
        

    def getRandom(self):
        """
        Get a random element from the set.
        :rtype: int
        """
        
        # getRandom time: more than O(1) for dict, O(1) for array
        return random.choice(self.l)


# Your RandomizedSet object will be instantiated and called as such:
# obj = RandomizedSet()
# param_1 = obj.insert(val)
# param_2 = obj.remove(val)
# param_3 = obj.getRandom()
原文地址:https://www.cnblogs.com/prmlab/p/7152849.html