LeetCode(380 & 381):O(1) 时间插入、删除和获取随机元素 Insert Delete GetRandom O(1)(Java)

234 篇文章 1 订阅
177 篇文章 0 订阅

2019.10.4 #程序员笔试必备# LeetCode 从零单刷个人笔记整理(持续更新)

github:https://github.com/ChopinXBP/LeetCode-Babel

数据结构题。通过一个ArrayList和一个HashMap就可以完成基础版的要求,ArrayList用于存放元素,HashMap用于存放元素在ArrayList中的下标。

插入时直接对ArrayList和HashMap分别插入即可。

删除元素时,HashMap可以在常数时间进行删除,但是ArrayList只有在尾部删除元素才能在常数时间进行,因此如果待删除的元素不在ArrayList的末尾,需要将其先和末尾元素进行交换。

随机访问元素只需要借助random.nextInt(nums.size()),就可以在0-size范围内等概率随机获得元素下标,再通过ArrayList访问即可。

升级版要求能够保存重复元素,只需要在基础版之上用HashMap+LinkedHashSet保存重复元素的下标即可。


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

传送门:O(1) 时间插入、删除和获取随机元素 - 允许重复

Design a data structure that supports all following operations in average O(1) time.

Note: Duplicate elements are allowed.

insert(val): Inserts an item val to the collection.

remove(val): Removes an item val from the collection if present.

getRandom: Returns a random element from current collection of elements. The probability of each element being returned is linearly related to the number of same value the collection contains.

设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构。

注意: 允许出现重复元素。

insert(val):向集合中插入元素 val。

remove(val):当 val 存在时,从集合中移除一个 val。

getRandom:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。

示例:
// 初始化一个空的集合。
RandomizedCollection collection = new RandomizedCollection();

// 向集合中插入 1 。返回 true 表示集合不包含 1 。
collection.insert(1);

// 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
collection.insert(1);

// 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
collection.insert(2);

// getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
collection.getRandom();

// 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
collection.remove(1);

// getRandom 应有相同概率返回 1 和 2 。
collection.getRandom();


import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashSet;
import java.util.Random;

/**
 *
 * Design a data structure that supports all following operations in average O(1) time.
 * Note: Duplicate elements are allowed.
 * insert(val): Inserts an item val to the set if not already present.
 * remove(val): Removes an item val from the set if present.
 * getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
 * 设计一个支持在平均 时间复杂度 O(1) 下,执行以下操作的数据结构。
 * 注意: 允许出现重复元素。
 * insert(val):当元素 val 不存在时,向集合中插入该项。
 * remove(val):元素 val 存在时,从集合中移除该项。
 * getRandom:随机返回现有集合中的一项。每个元素应该有相同的概率被返回。
 *
 */

public class InsertDeleteGetRandom {
    //元素不重复
    class RandomizedSet {

        //ArrayList用于存放元素,HashMap用于存放元素及其在ArrayList中的位置。
        ArrayList<Integer> nums;
        HashMap<Integer, Integer> locs;
        Random random;

        /** Initialize your data structure here. */
        public RandomizedSet() {
            nums = new ArrayList<>();
            locs = new HashMap<>();
            random = new Random();
        }

        /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
        public boolean insert(int val) {
            if(!locs.containsKey(val)){
                return false;
            }
            locs.put(val, nums.size());
            nums.add(val);
            return true;
        }

        /** Removes a value from the set. Returns true if the set contained the specified element. */
        //若待删除元素val不在ArrayList的末尾,则将其与末尾元素交换,再进行删除,由此保证o(1)的删除效率
        public boolean remove(int val) {
            if(!locs.containsKey(val)){
                return false;
            }
            int curLoc = locs.get(val);
            if(curLoc != nums.size() - 1){
                int lastValue = nums.get(nums.size() - 1);
                nums.set(curLoc, lastValue);
                locs.put(lastValue, curLoc);
            }
            locs.remove(val);
            nums.remove(nums.size() - 1);
            return true;
        }

        /** Get a random element from the set. */
        public int getRandom() {
            return nums.size() > 0 ? nums.get(random.nextInt(nums.size())) : Integer.MIN_VALUE;
        }
    }

    //允许元素重复
    class RandomizedCollection {

        //ArrayList用于存放元素,HashMap+LinkedHashSet用于存放重复元素在ArrayList中的位置。
        ArrayList<Integer> nums;
        HashMap<Integer, LinkedHashSet<Integer>> locs;
        Random random;

        /** Initialize your data structure here. */
        public RandomizedCollection() {
            nums = new ArrayList<>();
            locs = new HashMap<>();
            random = new Random();
        }

        /** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
        public boolean insert(int val) {
            boolean contain = locs.containsKey(val);
            if(!contain){
                locs.put(val, new LinkedHashSet<>());
            }
            locs.get(val).add(nums.size());
            nums.add(val);
            return !contain;
        }

        /** Removes a value from the set. Returns true if the set contained the specified element. */
        //若待删除元素val不在ArrayList的末尾,则将其与末尾元素交换,再进行删除,由此保证o(1)的删除效率
        public boolean remove(int val) {
            if(!locs.containsKey(val)){
                return false;
            }

            int curLoc = locs.get(val).iterator().next();
            //为防止末尾元素lastValue与当前元素val相同,先移除当前元素在LinkedHashSet中的下标curLoc
            locs.get(val).remove(curLoc);
            if (curLoc != nums.size() - 1) {
                int lastValue = nums.get(nums.size() - 1);
                nums.set(curLoc, lastValue);
                locs.get(lastValue).remove(nums.size() - 1);
                //若不先移除元素下标curLoc,则lastValue与val相同时无法添加
                locs.get(lastValue).add(curLoc);
            }
            nums.remove(nums.size() - 1);
            if(locs.get(val).isEmpty()){
                locs.remove(val);
            }

            return true;
        }

        /** Get a random element from the set. */
        public int getRandom() {
            return nums.size() > 0 ? nums.get(random.nextInt(nums.size())) : Integer.MIN_VALUE;
        }
    }

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




#Coding一小时,Copying一秒钟。留个言点个赞呗,谢谢你#

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值