Skip to content

Commit 6856f98

Browse files
committed
设计: O1数据结构
Change-Id: I15c2da20fc9c844f92ddcb052553cea1598a2901
1 parent 15c9faa commit 6856f98

File tree

1 file changed

+128
-0
lines changed

1 file changed

+128
-0
lines changed
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
// package leetcode
2+
3+
/*
4+
* @lc app=leetcode.cn id=381 lang=golang
5+
*
6+
* [381] O(1) 时间插入、删除和获取随机元素 - 允许重复
7+
*
8+
* https://leetcode-cn.com/problems/insert-delete-getrandom-o1-duplicates-allowed/description/
9+
*
10+
* algorithms
11+
* Hard (34.86%)
12+
* Likes: 31
13+
* Dislikes: 0
14+
* Total Accepted: 1.4K
15+
* Total Submissions: 3.7K
16+
* Testcase Example: '["RandomizedCollection","insert","insert","insert","getRandom","remove","getRandom"]\n[[],[1],[1],[2],[],[1],[]]'
17+
*
18+
* 设计一个支持在平均 时间复杂度 O(1) 下, 执行以下操作的数据结构。
19+
*
20+
* 注意: 允许出现重复元素。
21+
*
22+
*
23+
* insert(val):向集合中插入元素 val。
24+
* remove(val):当 val 存在时,从集合中移除一个 val。
25+
* getRandom:从现有集合中随机获取一个元素。每个元素被返回的概率应该与其在集合中的数量呈线性相关。
26+
*
27+
*
28+
* 示例:
29+
*
30+
* // 初始化一个空的集合。
31+
* RandomizedCollection collection = new RandomizedCollection();
32+
*
33+
* // 向集合中插入 1 。返回 true 表示集合不包含 1 。
34+
* collection.insert(1);
35+
*
36+
* // 向集合中插入另一个 1 。返回 false 表示集合包含 1 。集合现在包含 [1,1] 。
37+
* collection.insert(1);
38+
*
39+
* // 向集合中插入 2 ,返回 true 。集合现在包含 [1,1,2] 。
40+
* collection.insert(2);
41+
*
42+
* // getRandom 应当有 2/3 的概率返回 1 ,1/3 的概率返回 2 。
43+
* collection.getRandom();
44+
*
45+
* // 从集合中删除 1 ,返回 true 。集合现在包含 [1,2] 。
46+
* collection.remove(1);
47+
*
48+
* // getRandom 应有相同概率返回 1 和 2 。
49+
* collection.getRandom();
50+
*
51+
*
52+
*/
53+
54+
// @lc code=start
55+
import (
56+
"math/rand"
57+
)
58+
59+
type RandomizedCollection struct {
60+
Data map[int]map[int]bool // 用map存位置
61+
Index []int
62+
}
63+
64+
/** Initialize your data structure here. */
65+
func Constructor() RandomizedCollection {
66+
return RandomizedCollection{
67+
Data: map[int]map[int]bool{},
68+
Index: []int{},
69+
}
70+
}
71+
72+
/** Inserts a value to the collection. Returns true if the collection did not already contain the specified element. */
73+
func (this *RandomizedCollection) Insert(val int) bool {
74+
notFound := false
75+
if _, ok := this.Data[val]; !ok {
76+
this.Data[val] = map[int]bool{}
77+
notFound = true
78+
}
79+
this.Index = append(this.Index, val)
80+
this.Data[val][len(this.Index)-1] = true
81+
return notFound
82+
}
83+
84+
/** Removes a value from the collection. Returns true if the collection contained the specified element. */
85+
func (this *RandomizedCollection) Remove(val int) bool {
86+
dict, ok := this.Data[val]
87+
if !ok {
88+
return false
89+
}
90+
var target int
91+
for k := range dict {
92+
target = k
93+
break
94+
}
95+
if len(dict) <= 1 { // 清空
96+
delete(this.Data, val)
97+
} else {
98+
delete(dict, target)
99+
}
100+
lastIdx := len(this.Index) - 1
101+
lastVal := this.Index[lastIdx]
102+
if target < lastIdx {
103+
// 队尾的值挪到目标位然后去掉队尾
104+
this.Index[target] = lastVal
105+
}
106+
this.Index = this.Index[:lastIdx]
107+
lastDict := this.Data[lastVal]
108+
if len(lastDict) > 0 {
109+
lastDict[target] = true
110+
delete(lastDict, lastIdx)
111+
}
112+
return true
113+
}
114+
115+
/** Get a random element from the collection. */
116+
func (this *RandomizedCollection) GetRandom() int {
117+
idx := rand.Intn(len(this.Index))
118+
return this.Index[idx]
119+
}
120+
121+
/**
122+
* Your RandomizedCollection object will be instantiated and called as such:
123+
* obj := Constructor();
124+
* param_1 := obj.Insert(val);
125+
* param_2 := obj.Remove(val);
126+
* param_3 := obj.GetRandom();
127+
*/
128+
// @lc code=end

0 commit comments

Comments
 (0)