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()));
		}
	}
相关推荐
Robot_Nav2 分钟前
RC-ESDF与Lazy Theta* 算法结合进行离线全局路径的生成
算法·全局规划·esdf
papership4 分钟前
【入门级-算法-7、搜索算法:深度优先搜索】
算法·深度优先
一叶龙洲14 分钟前
Java中使用模板引擎(FreeMarker / Velocity) + Word XML导出复杂Word
xml·java·word
山甫aa17 分钟前
哈希集合-----从零开始的数据结构学习
数据结构·算法·哈希算法
say_fall20 分钟前
有关算法的简单数学问题
数据结构·c++·算法·职场和发展·蓝桥杯
Halo_tjn20 分钟前
Java 接口的定义重构学生管理系统
java·开发语言·算法
Albert Edison27 分钟前
【RabbitMQ】快速入门
java·分布式·rabbitmq
阿Y加油吧27 分钟前
栈的经典应用:从「有效括号」到「寻找两个正序数组的中位数」深度解析
开发语言·python·算法
ch.ju28 分钟前
Java程序设计(第3版)第二章——类型转换(1)
java
XiYang-DING30 分钟前
【Java】哈希
java·哈希算法·散列表