常数时间插入、删除和获取随机元素

常数时间插入、删除和获取随机元素

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

  • insert(val): 当元素val不存在时,向集合中插入该项。
  • remove(val): 元素val存在时,从集合中移除该项。
  • getRandom: 随机返回现有集合中的一项,每个元素应该有相同的概率被返回。

示例#

Copy
// 初始化一个空的集合。 RandomizedSet randomSet = new RandomizedSet(); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。 randomSet.insert(1); // 返回 false ,表示集合中不存在 2 。 randomSet.remove(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。 randomSet.insert(2); // getRandom 应随机返回 1 或 2 。 randomSet.getRandom(); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。 randomSet.remove(1); // 2 已在集合中,所以返回 false 。 randomSet.insert(2); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。 randomSet.getRandom();

题解#

Copy
/** * Initialize your data structure here. */ var RandomizedSet = function() { this.hashTable = {}; this.arr = []; }; /** * Inserts a value to the set. Returns true if the set did not already contain the specified element. * @param {number} val * @return {boolean} */ RandomizedSet.prototype.insert = function(val) { if(this.hashTable[val] !== undefined) return false; this.hashTable[val] = this.arr.length; this.arr.push(val); return true; }; /** * Removes a value from the set. Returns true if the set contained the specified element. * @param {number} val * @return {boolean} */ RandomizedSet.prototype.remove = function(val) { if(this.hashTable[val] === undefined) return false; var index = this.hashTable[val]; var key = this.arr[this.arr.length-1]; this.hashTable[key] = index; delete this.hashTable[val]; this.arr[index] = key; this.arr.pop(); return true; }; /** * Get a random element from the set. * @return {number} */ RandomizedSet.prototype.getRandom = function() { return this.arr[~~(Math.random() * this.arr.length)]; }; /** * Your RandomizedSet object will be instantiated and called as such: * var obj = new RandomizedSet() * var param_1 = obj.insert(val) * var param_2 = obj.remove(val) * var param_3 = obj.getRandom() */

思路#

题目要求实现对于插入与删除操作时间复杂度为O(1)的数据结构,很容易联想到链表与哈希表,题目还要求随机返回值的时间复杂度也是O(1),而单纯的链表与哈希表都无法满足这个要求,且在给定值的情况下链表的查找时间复杂度为O(n),不适用于本题,所以需要使用哈希表配合数组来实现,将值作为哈希表的key,在数组中的索引作为哈希表的value,这样对于insertgetRandom操作的时间复杂度都是O(1),对于remove操作需要将传入的value在数组中的索引值取出,然后将数组中最后一个值覆盖到这个索引,然后更改最后一个值在哈希表中的索引,最后删除数组中最后一个值以及哈希表中该值作为的key,这样就实现了O(1)复杂度的remove操作。首先在构造函数定义对象作为哈希表以及数组,在insert操作中,如果哈希表中已存在该值,则直接返回false,如果不存在则添加该值到哈希表作为key并将数组的长度作为值,在数组后追加该值,返回true,在remove操作中首先判断如果不存在该值则直接返回false,如果存在值则取出该值的index,然后将数组的最后一个值取出并在哈希表中将该值作为key,将index作为值,即将最后一个值覆盖到要删除的位置,然后将哈希表中要删除的值的索引删除,将数组的该值位置覆盖为最后一个值,然后删除数组中最后一个值,在getRandom操作中直接返回一个随机的数组值即可。

每日一题#

Copy
https://github.com/WindrunnerMax/EveryDay

参考#

Copy
https://leetcode-cn.com/problems/insert-delete-getrandom-o1
posted @   WindRunnerMax  阅读(195)  评论(0编辑  收藏  举报
编辑推荐:
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
阅读排行:
· 终于写完轮子一部分:tcp代理 了,记录一下
· 震惊!C++程序真的从main开始吗?99%的程序员都答错了
· 别再用vector<bool>了!Google高级工程师:这可能是STL最大的设计失误
· 单元测试从入门到精通
· 【硬核科普】Trae如何「偷看」你的代码?零基础破解AI编程运行原理
点击右上角即可分享
微信分享提示
CONTENTS