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

Insert Delete GetRandom O(1)


https://leetcode.com/problems/insert-delete-getrandom-o1/description/
import java.util.Random;

public class RandomizedSet {

    /** Initialize your data structure here. */
    Map<Integer, Integer> numToIdx;
    Map<Integer, Integer> idxToNum;
    
    public RandomizedSet() {
        numToIdx = new HashMap<>();
        idxToNum = 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 (numToIdx.containsKey(val)) {
            return false;
        }
        
        int idxForInsertion = numToIdx.size();
        numToIdx.put(val, idxForInsertion);
        idxToNum.put(idxForInsertion, val);
        return true;
    }
    
    /** Removes a value from the set. Returns true if the set contained the specified element. */
    public boolean remove(int val) {
        if (!numToIdx.containsKey(val)) {
            return false;
        }
        
        int idxOfVal = numToIdx.get(val);
        numToIdx.remove(val);
        idxToNum.remove(idxOfVal);
        
        if (numToIdx.size() == 0) {
            return true;
        }
        
        if (idxOfVal == numToIdx.size()) {
            return true;
        }
        
        // val was neither the only element, nor the last element.
        // after val was removed, we have to fill val's idx.
        // remove the last element in idxToNum and add it at idxOfVal instead.
        // the idx of the last element is idxToNum.size() as there were idxToNum.size() + 1 numbers
        // before val was removed and the last element had idx idxToNum.size()
        int numAtLastIdx = idxToNum.get(idxToNum.size());
        numToIdx.put(numAtLastIdx, idxOfVal);
        idxToNum.remove(idxToNum.size());
        idxToNum.put(idxOfVal, numAtLastIdx);
        return true;
    }
    
    /** Get a random element from the set. */
    public int getRandom() {
        if (numToIdx.size() == 0) {
            return -1;
        }
        
        if (numToIdx.size() == 1) {
            return idxToNum.get(0);
        }
        
        return idxToNum.get(new Random().nextInt(numToIdx.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();
 */