380. Insert Delete GetRandom O(1)

100 阅读1分钟

image.png

方法

  • 变长数组[]可以在 O(1) 的时间内完成获取随机元素操作,但是由于无法在 O(1) 的时间内判断元素是否存在,因此不能在 O(1)的时间内完成插入和删除操作

  • In a normal List, deleting from the middle is O(n) because it shifts everything after it.

  • So instead of removing from the middle, we:

  • Swap it with the last element, then remove the last element.

class RandomizedSet {
    Map<Integer, Integer> map; // val,val在list中的index
    List<Integer> list; // 存val
    Random rand;

    public RandomizedSet() {
        map = new HashMap<>();
        list = new ArrayList<>();
        rand = new Random();
    }
    
    // O(1)
    public boolean insert(int val) {
        if (map.containsKey(val)) {
            return false;
        }
        list.add(val);
        map.put(val, list.size() - 1);
        return true;
    }
    
    // In a normal List, deleting from the middle is O(n) because it shifts everything after it.
    // So instead of removing from the middle, we:
    // Swap it with the last element, then remove the last element.
    public boolean remove(int val) {
        if (!map.containsKey(val)) {
            return false;
        }

        int last = list.get(list.size() - 1);
        list.set(map.get(val), last);
        map.put(last, map.get(val));

        list.remove(list.size() - 1);
        map.remove(val);
        return true;
    }
    
    //There are no indexes in the hashmap, and hence to get a true random value, 
    // we need to convert hashmap keys in a list
    public int getRandom() {
        return list.get(rand.nextInt(list.size()));
    }
}

// 变长数组可以在 O(1) 的时间内完成获取随机元素操作,但是由于无法在 O(1) 的时间内判断元素是否存在,因此不能在 O(1)的时间内完成插入和删除操作

// 删除操作的重点在于将变长数组的最后一个元素移动到待删除元素的下标处,然后删除变长数组的最后一个元素。该操作的时间复杂度是 O(1),且可以保证在删除操作之后变长数组中的所有元素的下标都连续,方便插入操作和获取随机元素操作。