Monday, November 13, 2017

Insert Delete GetRandom O(1) - Duplicates allowed


https://leetcode.com/problems/insert-delete-getrandom-o1-duplicates-allowed/description/
public class RandomizedCollection {
    List<Integer> nums;
    Map<Integer, Set<Integer>> numsToIdxs;
    Random rand;

    /** Initialize your data structure here. */
    public RandomizedCollection() {
        nums = new ArrayList<Integer>();
        numsToIdxs = new HashMap<Integer, Set<Integer>>();
        rand = new Random();
    }

    /** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
    public boolean insert(int val) {
        boolean isValPresent = numsToIdxs.containsKey(val);
        if (!isValPresent) {
            numsToIdxs.put(val, new LinkedHashSet<Integer>());
        }
        
        numsToIdxs.get(val).add(nums.size());
        nums.add(val);
        return !isValPresent ;
    }

    /** Removes a value from the collection. Returns true if the collection contained the specified element. */
    public boolean remove(int val) {
        boolean isValPresent = numsToIdxs.containsKey(val);
        if (!isValPresent) {
            return false;
        }

        int idxOfVal = numsToIdxs.get(val).iterator().next();
        numsToIdxs.get(val).remove(idxOfVal);
        
        // since we removed one of the numbers, we have to check whether we removed the last number or not.
        // if we did not remove the last number in the list nums (which reflects insertion order), then we run into the scenario         // where numToIdx of the remaining nums at indices > idxOfVal is no longer correct. In order 
        // to fix this, we can remove the last element in nums and add it at idxOfVal. Update numToIdxs so that numAtLastIdx has 
        // its new index. Also remove idxOfVal from the list of indices for val / remove val from numToIdx if it had no 
        // duplicates.
        int lastIdx = nums.size() - 1;
        if (idxOfVal < lastIdx) {
            int numAtLastIdxInList = nums.get(lastIdx);
            nums.set(idxOfVal , numAtLastIdxInList);
            numsToIdxs.get(numAtLastIdxInList).remove(lastIdx);
            numsToIdxs.get(numAtLastIdxInList).add(idxOfVal);
        }
        nums.remove(lastIdx);

        if (numsToIdxs.get(val).isEmpty()) {
            numsToIdxs.remove(val);
        }
        return true;
    }

    /** Get a random element from the collection. */
    public int getRandom() {
        return nums.get(rand.nextInt(nums.size()));
    }
}

No comments:

Post a Comment