算法小知识-----04.13-----O(1) 时间插入、删除和获取随机元素

91 阅读2分钟

一起养成写作习惯!这是我参与「掘金日新计划 · 4 月更文挑战」的第12天,点击查看活动详情

今天疫情没有那么严重了,封控的家人也能见面了

O(1) 时间插入、删除和获取随机元素

该题出自力扣的380题 —— O(1) 时间插入、删除和获取随机元素【中等题】

审题

image.png

  • 该题的题意也相对比较简单,属于一道设计题
  • 设计出一个函数,包含三个方法,新增、删除、随机访问
  • 并且需要满足一个条件,就是每个方法的时间复杂度都为O(1)
  • 根据题意,需要满足时间复杂度为O(1),则新增与删除可以考虑用Map,满足随机访问 + 时间复杂度的方法,可以考虑用数组
  • 需要注意的是,HashMap,key存储值val,value存储数组的下标,对应着数组的下标存放的值val
    • 构造方法:
      • 初始化一个HashMap
      • 初始化一个Random随机方法
      • 初始化一个数组,并且给定长度为数组的最大长度2的5次方
      • 定义一个下标初始值 -1
    • 新增:
      • 判断map是否存在val,存在直接返回false
      • 存放数组,下标为初始值 +1
      • 存进Map
    • 删除方法:
      • 因为题意规定时间复杂度要O(1),而且选用了数组,就不存在删除这个说法
      • 所以就可以联想到删除链表节点 = 使指针取代它
      • 把要删除的值从HashMap中remove掉
      • 把当前值的下标与末尾下标对调,使末尾的值存放在当前的下标中,初始下标--
    • 随机方法
      • 直接调用Random方法,限制范围在index+1内

编码

class RandomizedSet {

    Map<Integer,Integer> map;
    int[] nums;
    Random random;
    int index = -1;

    /**
     * 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();
     */
    public RandomizedSet() {
        map = new HashMap<>();
        nums = new int[20000];
        random = new Random();
    }

    public boolean insert(int val) {
        if (map.containsKey(val))return false;
        nums[++index] = val;
        map.put(val,index);
        return true;
    }

    public boolean remove(int val) {
        if (!map.containsKey(val))return false;
        int last = map.remove(val);
        //末尾对调 + index --
        if (last != index){
            //不是末尾
            map.put(nums[index],last);
        }
        nums[last] = nums[index--];
        return true;
    }

    public int getRandom() {
       return nums[random.nextInt(index +1)];
    }
}

image.png