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

Leetcode380不同的是,这道题允许元素重复

代码逻辑

1. 插入操作
java 复制代码
public boolean insert(int val) {
    arr.add(val);  // 直接添加到数组末尾
    HashSet<Integer> set = map.getOrDefault(val, new HashSet<Integer>());
    set.add(arr.size() - 1);  // 记录该元素在数组中的索引
    map.put(val, set);
    return set.size() == 1;  // 如果是第一次插入,返回 true
}

将元素添加到数组末尾,同时在 HashMap 中记录其索引位置。

2. 删除操作
java 复制代码
public boolean remove(int val) {
    if (!map.containsKey(val)) {
        return false;
    }
    
    // 获取要删除元素的任意一个索引
    HashSet<Integer> valSet = map.get(val);
    int valAnyIndex = valSet.iterator().next();
    
    // 获取数组末尾元素
    int endValue = arr.get(arr.size() - 1);
    
    if (val == endValue) {
        // 特殊情况:要删除的就是末尾元素
        valSet.remove(arr.size() - 1);
    } else {
        // 将末尾元素移动到要删除的位置
        HashSet<Integer> endValueSet = map.get(endValue);
        endValueSet.add(valAnyIndex);  // 末尾元素有了新位置
        arr.set(valAnyIndex, endValue);  // 更新数组
        endValueSet.remove(arr.size() - 1);  // 移除末尾位置
        valSet.remove(valAnyIndex);  // 移除被删除元素的位置
    }
    
    arr.remove(arr.size() - 1);  // 删除数组末尾
    
    if (valSet.isEmpty()) {
        map.remove(val);  // 如果该值已经没有了,从 map 中删除
    }
    
    return true;
}

ArrayList 删除中间元素是 O(n) 操作,但删除末尾元素是 O(1),因此我们把要删除的元素和末尾元素交换,然后删除末尾。

3. 随机获取
java 复制代码
public int getRandom() {
    return arr.get((int) (Math.random() * arr.size()));
}

完整代码

java 复制代码
class RandomizedCollection{
		public HashMap<Integer,HashSet<Integer>> map;
		public ArrayList<Integer> arr;
		public RandomizedCollection(){
			map = new HashMap<>();
			arr = new ArrayList<>();
		}

		public boolean insert(int val) {
			arr.add(val);  // 直接添加到数组末尾
			HashSet<Integer> set = map.getOrDefault(val, new HashSet<Integer>());
			set.add(arr.size() - 1);  // 记录该元素在数组中的索引
			map.put(val, set);
			return set.size() == 1;  // 如果是第一次插入,返回 true
		}

		public boolean remove(int val) {
			if (!map.containsKey(val)) {
				return false;
			}

			// 获取要删除元素的任意一个索引
			HashSet<Integer> valSet = map.get(val);
			int valAnyIndex = valSet.iterator().next();

			// 获取数组末尾元素
			int endValue = arr.get(arr.size() - 1);

			if (val == endValue) {
				// 特殊情况:要删除的就是末尾元素
				valSet.remove(arr.size() - 1);
			} else {
				// 将末尾元素移动到要删除的位置
				HashSet<Integer> endValueSet = map.get(endValue);
				endValueSet.add(valAnyIndex);  // 末尾元素有了新位置
				arr.set(valAnyIndex, endValue);  // 更新数组
				endValueSet.remove(arr.size() - 1);  // 移除末尾位置
				valSet.remove(valAnyIndex);  // 移除被删除元素的位置
			}

			arr.remove(arr.size() - 1);  // 删除数组末尾

			if (valSet.isEmpty()) {
				map.remove(val);  // 如果该值已经没有了,从 map 中删除
			}

			return true;
		}

		public int getRandom(){
			return arr.get((int) (Math.random()*arr.size()));
		}
	}
相关推荐
fengfuyao9856 分钟前
基于MATLAB的表面织构油润滑轴承故障频率提取(改进VMD算法)
人工智能·算法·matlab
Java面试题总结7 分钟前
基于 Java 的 PDF 文本水印实现方案(iText7 示例)
java·python·pdf
机器学习之心14 分钟前
基于随机森林模型的轴承剩余寿命预测MATLAB实现!
算法·随机森林·matlab
一只小小的芙厨16 分钟前
寒假集训笔记·树上背包
c++·笔记·算法·动态规划
马猴烧酒.20 分钟前
【面试八股|Java集合】Java集合常考面试题详解
java·开发语言·python·面试·八股
庄周迷蝴蝶23 分钟前
四、CUDA排序算法实现
算法·排序算法
以卿a26 分钟前
C++(继承)
开发语言·c++·算法
I_LPL29 分钟前
day22 代码随想录算法训练营 回溯专题1
算法·回溯算法·求职面试·组合问题
金融RPA机器人丨实在智能33 分钟前
2026动态规划新风向:实在智能Agent如何以自适应逻辑重构企业效率?
算法·ai·重构·动态规划
测试工程师成长之路36 分钟前
Serenity BDD 框架:Java + Selenium 全面指南(2026 最新)
java·开发语言·selenium