hello 大家好!今天开写一个新章节,每一天一道算法题。让我们一起来学习算法思维吧!
为了实现 RandomizedSet 类,并且保证每个函数的平均时间复杂度为0(1) ,我们可以结合使用数组和哈希表。数组用于存储集合中的元素,哈希表用于记录每个元素在数组中的索引位置。这样在插入、删除和随机获取元素时都能高效地完成操作。
以下是实现代码及详细注释:
class RandomizedSet {
constructor() {
// 用于存储集合中的元素
this.nums = [];
// 用于记录每个元素在数组中的索引位置
this.valToIndex = new Map();
}
/**
* 向集合中插入元素
* @param {number} val - 要插入的元素
* @return {boolean} - 如果元素不存在并成功插入返回 true,否则返回 false
*/
insert(val) {
// 检查元素是否已经存在于集合中
if (this.valToIndex.has(val)) {
return false;
}
// 将元素添加到数组末尾
this.nums.push(val);
// 记录元素在数组中的索引
this.valToIndex.set(val, this.nums.length - 1);
return true;
}
/**
* 从集合中移除元素
* @param {number} val - 要移除的元素
* @return {boolean} - 如果元素存在并成功移除返回 true,否则返回 false
*/
remove(val) {
// 检查元素是否存在于集合中
if (!this.valToIndex.has(val)) {
return false;
}
// 获取要移除元素的索引
const index = this.valToIndex.get(val);
// 获取数组的最后一个元素
const lastVal = this.nums[this.nums.length - 1];
// 将最后一个元素移动到要移除元素的位置
this.nums[index] = lastVal;
// 更新最后一个元素在哈希表中的索引
this.valToIndex.set(lastVal, index);
// 移除数组的最后一个元素
this.nums.pop();
// 从哈希表中删除要移除元素的记录
this.valToIndex.delete(val);
return true;
}
/**
* 随机返回集合中的一个元素
* @return {number} - 随机返回的元素
*/
getRandom() {
// 生成一个 0 到数组长度减 1 之间的随机索引
const randomIndex = Math.floor(Math.random() * this.nums.length);
// 返回该索引对应的元素
return this.nums[randomIndex];
}
}
代码解释:
构造函数 constructor():
this.nums:一个数组,用于存储集合中的元素。
this.valToIndex:一个 Map 对象,用于记录每个元素在数组中的索引位置,键为元素值,值为该元素在数组中的索引。
插入方法 insert(val):
首先检查 valToIndex 中是否已经存在该元素,如果存在则返回 false。
若不存在,将元素添加到 nums 数组的末尾,并将该元素及其在数组中的索引记录到 valToIndex 中,最后返回 true。
移除方法 remove(val):
先检查 valToIndex 中是否存在该元素,若不存在则返回 false。
若存在,获取该元素在数组中的索引 index,同时获取数组的最后一个元素 lastVal。
将 lastVal 移动到 index 位置,并更新 lastVal 在 valToIndex 中的索引。
移除 nums 数组的最后一个元素,并从 valToIndex 中删除要移除元素的记录,最后返回 true。
随机获取元素方法 getRandom():
使用 Math.random() 生成一个 0 到 1 之间的随机数,乘以数组的长度并向下取整,得到一个随机索引 randomIndex。
返回 nums 数组中 randomIndex 位置的元素。