Design a data structure that supports all following operations in O(1) time.
insert(val): Inserts an item val to the set if not already present.
remove(val): Removes an item val from the set if present.
getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
分析:
因为要求所有操作O(1),插入可以满足这个条件,如果用数组来存储值,getRandom可以满足O(1).但是要求不能重复和delete的时候也满足这个条件,只能使用一个map. key是值,value是位置。
1 public class RandomizedSet { 2 ArrayList<Integer> nums;//值 3 // value to position 4 HashMap<Integer, Integer> valueToPositionMap; 5 Random rand; 6 7 public RandomizedSet() { 8 nums = new ArrayList<>(); 9 valueToPositionMap = new HashMap<>(); 10 rand = new Random(System.currentTimeMillis()); 11 } 12 13 /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */ 14 public boolean insert(int val) { 15 boolean isContained = valueToPositionMap.containsKey(val); 16 if ( isContained ) return false; 17 valueToPositionMap.put( val, nums.size()); 18 nums.add(val); 19 return true; 20 } 21 22 /** Removes a value from the set. Returns true if the set contained the specified element. */ 23 public boolean remove(int val) { 24 boolean isContained = valueToPositionMap.containsKey(val); 25 if ( ! isContained ) return false; 26 int position = valueToPositionMap.get(val); 27 if (position != nums.size() - 1 ) { 28 // put the true last one to 'position' in nums 29 int lastOne = nums.get(nums.size() - 1 ); 30 nums.set( position , lastOne ); 31 valueToPositionMap.put(lastOne, position); 32 } 33 valueToPositionMap.remove(val); 34 nums.remove(nums.size() - 1); 35 return true; 36 } 37 38 /** Get a random element from the set. */ 39 public int getRandom() { 40 return nums.get( rand.nextInt(nums.size()) ); 41 } 42 }
第二种情况:允许有重复数值。
用set来记录同一个值出现的位置,如果被删除的数不是最后一个,则和最后一个换一下位置,然后删除就可以了。
1 public class RandomizedCollection { 2 List<Integer> nums; 3 Map<Integer, Set<Integer>> valueToPositionMap; 4 Random rand; 5 6 public RandomizedCollection() { 7 nums = new ArrayList<>(); 8 valueToPositionMap = new HashMap<>(); 9 rand = new Random(System.currentTimeMillis()); 10 } 11 12 /** 13 * Inserts a value to the collection. Returns true if the collection did not 14 * already contain the specified element. 15 */ 16 public boolean insert(int val) { 17 boolean isContained = valueToPositionMap.containsKey(val); 18 if (!isContained) { 19 valueToPositionMap.put(val, new HashSet<>()); 20 } 21 valueToPositionMap.get(val).add(nums.size()); 22 nums.add(val); 23 return !isContained; 24 } 25 26 /** 27 * Removes a value from the collection. Returns true if the collection contained 28 * the specified element. 29 */ 30 public boolean remove(int val) { 31 if (!valueToPositionMap.containsKey(val)) { 32 return false; 33 } 34 if (!valueToPositionMap.get(val).contains(nums.size() - 1)) { 35 int currPos = valueToPositionMap.get(val).iterator().next(); 36 int lastVal = nums.get(nums.size() - 1); 37 valueToPositionMap.get(lastVal).remove(nums.size() - 1); 38 valueToPositionMap.get(lastVal).add(currPos); 39 valueToPositionMap.get(val).remove(currPos); 40 valueToPositionMap.get(val).add(nums.size() - 1); 41 nums.set(currPos, lastVal); 42 } 43 valueToPositionMap.get(val).remove(nums.size() - 1); 44 if (valueToPositionMap.get(val).isEmpty()) { 45 valueToPositionMap.remove(val); 46 } 47 nums.remove(nums.size() - 1); 48 return true; 49 } 50 51 /** Get a random element from the collection. */ 52 public int getRandom() { 53 return nums.get(rand.nextInt(nums.size())); 54 } 55 }