LeetCode381 Insert Delete GetRandom O(1) - Duplicates allowed

this is the follow up of Leetcode380, which allows dupliciate values added in item pool.
if you recall the solution we use to solve LC380, list and hashmap used in that. and list stores the elements and hashmap stores the value and its index as k-v pair. so each value have only one index.
now, each value will have more than one index.

so now, we still have two rules:

  1. insert() remove() and getRandom() all needs O(1)
  2. getRandom() still needs to return the value by same possibility.

now, we need to make more improvement about our previous solution,

    ArrayList<Integer> lst;
    HashMap<Integer, Set<Integer>> idx;

and that set in hashmap stores indexes of current element.

and the code is complicated,

public class RandomizedCollection {
    ArrayList<Integer> lst;
    HashMap<Integer, HashSet<Integer>> idx;
    Random rand = new Random();
    /** Initialize your data structure here. */

    public RandomizedCollection() {
        lst = new ArrayList<Integer>();
	    idx = new HashMap<Integer, HashSet<Integer>>();
    }

    /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
    //but if we already contains this value, we can still insert it.
    public boolean insert(int val) {
        if (!idx.containsKey(val)) idx.put(val, new HashSet<Integer>());
        idx.get(val).add(lst.size());
        lst.add(val);
        return idx.get(val).size() == 1;
    }

    /** Removes a value from the collection. Returns true if the collection contained the specified element. */
    public boolean remove(int val) {
        if (!idx.containsKey(val) || idx.get(val).size() == 0) return false;
	    int remove_idx = idx.get(val).iterator().next(); //iterator of the set
        idx.get(val).remove(remove_idx);
        int last = lst.get(lst.size() - 1);
        lst.set(remove_idx, last);
        idx.get(last).add(remove_idx); 
        idx.get(last).remove(lst.size() - 1);

	    lst.remove(lst.size() - 1);
        return true;
    }

    /** Get a random element from the collection. */
    public int getRandom() {
        return lst.get(rand.nextInt(lst.size())); //this can retrive everything with same possibility
    }
}
/**
 * Your RandomizedCollection object will be instantiated and called as such:
 * RandomizedCollection obj = new RandomizedCollection();
 * boolean param_1 = obj.insert(val);
 * boolean param_2 = obj.remove(val);
 * int param_3 = obj.getRandom();
 */

12/08/2020 revisit:
总结一下 这道题在思路上和380类似,所不同的是 同一个val可能对应多个不同的index.而之前只对应一个。
所以 我们的HashMap从HashMap<Integer, Integer> 变成了 HashMap<Integer, HashSet< Integer >>
但是仍然k-v对应 val-index(s)
而每次我们remove的时候 我们也是跟之前一样处理,就是swap到尾部进行删除。注意hashmap的更新就可以了。

posted @ 2020-06-13 03:18  EvanMeetTheWorld  阅读(20)  评论(0)    收藏  举报