380. O(1) 时间插入、删除和获取随机元素
实现RandomizedSet 类:
- RandomizedSet() 初始化 RandomizedSet 对象
- bool insert(int val) 当元素 val 不存在时,向集合中插入该项,并返回 true ;否则,返回 false 。
- bool remove(int val) 当元素 val 存在时,从集合中移除该项,并返回 true ;否则,返回 false 。
- int getRandom() 随机返回现有集合中的一项(测试用例保证调用此方法时集合中至少存在一个元素)。
每个元素应该有 相同的概率 被返回。
你必须实现类的所有函数,并满足每个函数的 平均 时间复杂度为 O(1) 。
示例:
输入 [“RandomizedSet”, “insert”, “remove”, “insert”, “getRandom”, “remove”, “insert”, “getRandom”] [[], [1], [2], [2], [], [1], [2],
[]]
输出 [null, true, false, true, 2, true, false, 2]解释 RandomizedSet randomizedSet = new RandomizedSet(); randomizedSet.insert(1); // 向集合中插入 1 。返回 true 表示 1 被成功地插入。
randomizedSet.remove(2); // 返回 false ,表示集合中不存在 2 。
randomizedSet.insert(2); // 向集合中插入 2 。返回 true 。集合现在包含 [1,2] 。
randomizedSet.getRandom(); // getRandom 应随机返回 1 或 2 。
randomizedSet.remove(1); // 从集合中移除 1 ,返回 true 。集合现在包含 [2] 。
randomizedSet.insert(2); // 2 已在集合中,所以返回 false 。
randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom 总是返回 2 。
提示:
- -2^31 <= val <= 2^31 - 1
- 最多调用 insert、remove 和 getRandom 函数 2 * 10^5 次
- 在调用 getRandom 方法时,数据结构中 至少存在一个 元素。
解题思路
本题关键点在于如何保证等概率,直接上代码。
Go代码
type RandomizedSet struct {
set map[int]bool // 在go中并没有set结构,但可以用map模拟
}
func Constructor() RandomizedSet {
temp := RandomizedSet{
set : make(map[int]bool),
}
return temp
}
func (this *RandomizedSet) Insert(val int) bool {
if this.set[val] { // 已有该元素时不允许插入,并返回false
return false
}
this.set[val] = true
return true
}
func (this *RandomizedSet) Remove(val int) bool {
if this.set[val] { // 已有该元素时删除该元素,并返回true
delete(this.set,val)
return true
}
return false
}
func (this *RandomizedSet) GetRandom() int {
num := rand.Intn(len(this.set)) // 平均分布获得一个随机数,满足题目要求的等概率随机 获取一个元素
i := 0
for key,_ := range this.set {
if i == num { //i等于随机数num,返回key
return key
}
i++ // i不断++,总会有一次等于num的,此时的key就算是等概率随机获取的
}
return -1
}
/**
* Your RandomizedSet object will be instantiated and called as such:
* obj := Constructor();
* param_1 := obj.Insert(val);
* param_2 := obj.Remove(val);
* param_3 := obj.GetRandom();
*/