LeetCode - 381. Insert Delete GetRandom O(1) - Duplicates allowed(允许重复)

本文介绍LeetCode-381题的解决方案,该题要求实现一个允许重复元素的随机集合,通过使用HashMap和ArrayList组合,详细解释了插入、删除和随机获取元素的高效算法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

LeetCode - 381. Insert Delete GetRandom O(1) - Duplicates allowed(允许重复)

题目链接
题目

在这里插入图片描述

解析

做这题之前先做LeetCode - 380

这一题加上了可以加入重复的元素,题目就变得复杂了一些。

  • 大体思路还是使用HashMap + ArrayList,只不过MapHashMap<Integer, ArrayList<Integer>>的形式,而List则是ArrayList<int[]>形式;
  • 其中Mapkey存的是值val,而对应的value存的是一个下标的集合,即List中值是val的下标的集合;
  • List中每个位置也要存两个信息,一个是值val(数组[0]位置),另一个存这个值valmap中的下标集合中的位置(数组[1]位置);

下图展示了存储

容器中有261829

在这里插入图片描述

添加元素很简单,维护maplist即可。

例如添加元素6:
在这里插入图片描述

删除元素思想也是和最后一个元素交换位置,不过也要维护相应的信息即可。

删除元素9:
在这里插入图片描述

class RandomizedCollection {

    private HashMap<Integer, ArrayList<Integer>>valIndexsMap;
    private ArrayList<int[]> vals;   // store the position in the map's value

    public RandomizedCollection() {
        valIndexsMap = new HashMap<>();
        vals = new ArrayList<>();
    }

    public boolean insert(int val) {
        boolean contain = !valIndexsMap.containsKey(val);
//        ArrayList<Integer>indexs = valIndexsMap.get(val);
//        if(indexs == null){
//            indexs = new ArrayList<>();
//        }
//        indexs.add(vals.size());
        ArrayList<Integer>indexs = valIndexsMap.computeIfAbsent(val, k -> new ArrayList<>());
        indexs.add(vals.size());
        vals.add(new int[]{val, indexs.size()-1});
        return contain;
    }

    public boolean remove(int val) {
        if(!valIndexsMap.containsKey(val))
            return false;
        ArrayList<Integer>indexs = valIndexsMap.get(val);
        int removeIndex = indexs.get(indexs.size() - 1);
        indexs.remove(indexs.size()-1);
        if(indexs.isEmpty())
            valIndexsMap.remove(val);

        if(removeIndex < vals.size()-1){ // exchange
            // 将最后一个元素放在 removeIndex位置
            vals.get(removeIndex)[0] = vals.get(vals.size()-1)[0];
            vals.get(removeIndex)[1] = vals.get(vals.size()-1)[1];
            valIndexsMap.get(vals.get(removeIndex)[0]).set(vals.get(removeIndex)[1], removeIndex);
        }
        vals.remove(vals.size()-1);
        return true;
    }

    public int getRandom() {
        return vals.get((int)(Math.random() * vals.size()))[0];
    }
}

这里注意Java8computeIfAbsent用法:

类似下面的用法

Object key = map.get("key");
if (key == null) {
    key = new Object();
    map.put("key", key);
}
//上面的操作可以简化为一行,若key对应的value为空,会将第二个参数的返回值存入并返回
Object key2 = map.computeIfAbsent("key", k -> new Object());

具体用法举例:

import java.util.*;

public class Test {

    public static void main(String[] args){
        Map<String, List<String>> map = new HashMap<>();
        List<String> list;

        list = map.get("list-1");
        if (list == null) {
            list = new ArrayList<>();
            map.put("list-1", list);
        }
        list.add("one");

        //使用 computeIfAbsent 可以这样写
        map.computeIfAbsent("list-1", k -> new ArrayList<>()).add("one");

        System.out.println(map); //  {list-1=[one, one]}
    }
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值