插入、删除和随机访问都是O(1)的容器

        由于题目要求插入和删除的时间复杂度都是O(1),能同时满足这些时间效率要求的只有哈希表,由此要用到哈希表。题目还要求可以在 O(1) 时间内随机返回数据集中的数值,数组可以做到,所以还需要用到数组。

        数组中存放数值,可以实现在O(1) 时间内随机返回数据集中的数值,同时,哈希表需要知道每个数值在数组中的位置,否则删除数组的数值时就要顺序扫描整个数组。所以哈希表中键是数值,而其对应的值是它在数组中的位置。

public class RandomizedSet {
    private Map<Integer, Integer> valueToIndex;
    private List<Integer> values;
    private Random random;

    // 确保每个 RandomizedSet 对象都有自己独立的成员变量实例,避免不同对象之间共享数据
    public RandomizedSet() {
        valueToIndex = new HashMap<>();
        values = new ArrayList<>();
        random = new Random();
    }

    public boolean insert(int val) {
        if (valueToIndex.containsKey(val)) {
            return false;
        }
        valueToIndex.put(val, values.size());
        values.add(val);
        return true;
    }

    public boolean remove(int val) {
        if (!valueToIndex.containsKey(val)) {
            return false;
        }
        int index = valueToIndex.get(val);
        int lastElement = values.get(values.size() - 1);

        // 将最后一个元素移动到要删除元素的位置
        values.set(index, lastElement);
        valueToIndex.put(lastElement, index);

        // 删除最后一个元素
        values.remove(values.size() - 1);
        valueToIndex.remove(val);
        
        return true;
    }

    public int getRandom() {
        int randomIndex = random.nextInt(values.size());
        return values.get(randomIndex);
    }
}

        在数组和HashMap尾部添加数据的操作都是O(1),所以没什么好说的,就是别忘了考虑数据若已经存在,则不能添加,返回false。

        删除数值前也要考虑数据集中是否存在该数据,没有则返回false。从哈希表中用O(1)时间删除数据比较简单,之间调用remove方法即可,但从数值中用O(1)时间删除数值,不能简单的remove了,因为被删除的数值不一定位于数组的尾部,当数组中间的数值被删除之后,为了保证数组内存的连续性,被删除之后的数字都要向前移动,由此删除的时间复杂度是O(n)了。所以为了避免数组中删除数值时移动数据,可以用数值尾部的数据替换掉把被删除的数字,同时删除数组中最后的数字。这样时间复杂度就是O(1).

        以相同概率随机返回数据可以用函数random.nextInt随机生成一个整数,将其当作下标即可。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不过是条河鱼

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值