LeetCode380 Insert Delete GetRandom() in O(1)

implement a data structure that support insert() delete() and getRandom()
and there are few points we should keep in mind:

  1. every method needs to be done in O(1)
  2. the getrandom() should return each item in our items pool with the same probability

let’s first take a look at the rule2, this can be easily solved in:

Random rand = new Random();
rand.nextInt(val); ..this will return a random value from [0, val-1], so we can use this to retrive indexes randomly

so starting from rule1, we know hashmap can search an element in O(1), and if each time we remove or add the last position of list, that will takes O(1) as well, and besides, if we know the index, then we can retrieve element from an array in O(1).
and we need to implement three method. if we use hashmap, then insert and remove defintly can be done in O(1). but how can we retrieve a element in hashmap randomly? because hashmap have no indexes. so we need list(but why not array? because we need to insert and remove elements).
than means, we need to combine list and hashmap. and maintain those two things in insert() or delete().
when we need to insert something new, if hashmap already contains that, then we return false; if it didn’t then we update map and list.
when we need to remove something, if this value not in hashmap, then just return false; if it is in hashmap, then we need to remove this value from hashmap and list. and of course we can remove it in hashmap using O(1), but not in list, if we know the index of needs-to-be- removed elements, then we can remove the element in list in O(1). so we store every element and its index in hashmap.
so:

        int index = map.remove(val); //get the val's index in this list
        int lastVal = list.remove(list.size() - 1); //and list will remove it's lastIndex value
        if(index != list.size()) { //this if statement, shows that you don't have to do anything if the remove element is the last element of list
            list.set(index, lastVal); //we just need this lastVal to fill the gap produced by remove the val in list(why do we need to do this? because if we just list.remove(index), then everything behind will be moveforward, and every index we stored in hashmap will need to be updated, and it's time consuming)
            map.put(lastVal, index); //and because we poll up the last value to fill the gap, then we only needs to update the index of lastVal.
        }

and you have to say, the idea of previous code is concise and precise.
Just Brilliant!
so this seems like a Random() problem, but the random part is the easest part.


class RandomizedSet {
    
    private HashMap<Integer, Integer> map;
    private List<Integer> list;
    private Random rand;

    /** Initialize your data structure here. */
    public RandomizedSet() {
        map = new HashMap<>();
        list = new ArrayList<>();
        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) {
        if(map.containsKey(val)) {
            return false;
        } else {
            list.add(val);
            map.put(val, list.size() - 1); //update the index of this value
            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 index = map.remove(val); //get the val's index in this list
        int lastVal = list.remove(list.size() - 1); //and list will remove it's lastIndex value
        if(index != list.size()) { //this if statement, shows that you don't have to do anything if the remove element is the last element of list
            list.set(index, lastVal);
            map.put(lastVal, index);
        }
        
        return true;
    }
    
    /** Get a random element from the set. */
    public int getRandom() {

        return list.get(rand.nextInt(list.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();
 */

12/08.2020 revisit:
let’s summarize this question.
we need to inplement a randomizedSet, which allows us to insert, remove and getRandom() in the O(1).
idea:
if we want to insert something in O(1), we could use (add in arrayList, put in hashmap)
if we want to remove something in O(1), we could use hashmap,
if we want to getRandom() in O(1), we could use get in arrayList, but we need to generate a random index first.

so we maintain two things:
an arraylist, and a hashmap.
insert: always added to the last position. and update k-v as val, list.size() - 1; //and we need to check if map contains this val first, if it is, then we can’t insert
remove: first check if map contains this key too. if it contains, then we continue. and each time we get the index of this value, but instead we remove it directly from list, we switch the position of val and the last value of this list, and then remove the last one. and don’t forget to update the new index of previous last value.
getRandom(): we use random to generate a number from [0, list.size()) and list.get(index).

posted @ 2020-06-13 02:54  EvanMeetTheWorld  阅读(23)  评论(0)    收藏  举报