1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42
| class RandomizedSet { List<Integer> list; Map<Integer, Integer> map; Random rand;
public RandomizedSet() { list = new ArrayList<>(); map = new HashMap<>(); rand = new Random(); }
public boolean insert(int val) { if (!map.containsKey(val)) { list.add(val); map.put(val, list.size() - 1); return true; } return false; }
public boolean remove(int val) { if (map.containsKey(val)) { int candidateIdx = map.get(val); swap(list, candidateIdx, list.size() - 1); map.put(list.get(candidateIdx), candidateIdx); map.remove(val); list.remove(list.size() - 1); return true; } return false; }
public int getRandom() { return list.get(rand.nextInt(list.size())); }
private void swap(List<Integer> list, int i, int j) { int temp = list.get(i); list.set(i, list.get(j)); list.set(j, temp); } }
|
骚操作就是, 为了移除中间的某个element, 先让它和最后一个element交换位置, 然后移除最后一个element即可. 这样就是O(1)的remove了. 但是这会破坏原来元素之间的相对位置, 本来是最后一个的element被移动到了中间某个位置. 当然这道题里面, 这不影响什么, 但是不要把这种操作用到那些在意元素间相对位置不变的情况.
同样地第27行代码的位置很关键. 有一个edge case就是如果list中只剩一下一个元素, 而且我们刚好要移走它. 如果27行代码写的比较靠前, 比如插在24和25行之间, 那么25行就会抛出异常因为此时list中没有元素了. 因此我们要把这行代码放到25行之后.
时间复杂度: 每一个method都是O(1) 因为这是题目规定.
空间复杂度: O(n) n为list中元素最多的时候元素的个数.