LeetCode 380. Insert Delete GetRandom O(1)

Implement the RandomizedSet class:

  • RandomizedSet() Initializes the RandomizedSet object.
  • bool insert(int val) Inserts an item val into the set if not present. Returns true if the item was not present, false otherwise.
  • bool remove(int val) Removes an item val from the set if present. Returns true if the item was present, false otherwise.
  • int getRandom() Returns a random element from the current set of elements (it's guaranteed that at least one element exists when this method is called). Each element must have the same probability of being returned.

You must implement the functions of the class such that each function works in average O(1) time complexity.

Example 1:

Input
["RandomizedSet", "insert", "remove", "insert", "getRandom", "remove", "insert", "getRandom"]
[[], [1], [2], [2], [], [1], [2], []]
Output
[null, true, false, true, 2, true, false, 2]

Explanation
RandomizedSet randomizedSet = new RandomizedSet();
randomizedSet.insert(1); // Inserts 1 to the set. Returns true as 1 was inserted successfully.
randomizedSet.remove(2); // Returns false as 2 does not exist in the set.
randomizedSet.insert(2); // Inserts 2 to the set, returns true. Set now contains [1,2].
randomizedSet.getRandom(); // getRandom() should return either 1 or 2 randomly.
randomizedSet.remove(1); // Removes 1 from the set, returns true. Set now contains [2].
randomizedSet.insert(2); // 2 was already in the set, so return false.
randomizedSet.getRandom(); // Since 2 is the only number in the set, getRandom() will always return 2.

Constraints:

  • -231 <= val <= 231 - 1
  • At most 2 * 105 calls will be made to insertremove, and getRandom.
  • There will be at least one element in the data structure when getRandom is called.

这题让你实现一个random set,其实本质就是让你能在一个set里return一个random number in the set。要求时间复杂度为O(1)。

很容易能想到就是至少要定义一个hashset,正常insert / remove,然后再搞一个random number generator每次generate一个random number。但是怎么把random number对应到set里的值呢,很容易能想到那就把set里的值每个assing一个index,generate一个random index然后return它对应的set的值就好了。那怎么才能知道这个set里的值对应的index呢,那就把hashset变成hashmap,记录val -> index就行了。

那么问题来了,remove的时候还得remove from list,这会导致在除了remove最后一个元素以外的其他时候都是O(n)复杂度。这时候用的trick就是我们把remove的数字和最后一个数字交换一下,然后remove最后一个,就能保证O(1)的复杂度了,毕竟咱也不care这个list里的顺序。代码写起来还算比较简单吧,没啥坑。

class RandomizedSet {

    private Map<Integer, Integer> valToIndex;
    private List<Integer> list;
    private Random rand = new Random();

    public RandomizedSet() {
        valToIndex = new HashMap<>();
        list = new ArrayList<>();
    }
    
    public boolean insert(int val) {
        if (valToIndex.containsKey(val)) {
            return false;
        }
        valToIndex.put(val, list.size());
        list.add(val);
        return true;
    }
    
    public boolean remove(int val) {
        if (!valToIndex.containsKey(val)) {
            return false;
        }
        int index = valToIndex.get(val);
        if (index != list.size() - 1) {
            int lastVal = list.get(list.size() - 1);
            list.set(index, lastVal);
            valToIndex.put(lastVal, index);
        }
        list.remove(list.size() - 1);
        valToIndex.remove(val);
        return true;
    }
    
    public int getRandom() {
        int nextRand = rand.nextInt(list.size());
        return list.get(nextRand);
    }
}

/**
 * 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();
 */

  • 16
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值