@@ -57,12 +57,26 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
57
57
58
58
<!-- 这里可写通用的实现逻辑 -->
59
59
60
- “ 哈希表 + 动态列表”实现。
60
+ ** 方法一: 哈希表 + 动态列表**
61
61
62
62
哈希表存放每个元素的值和对应的下标,而动态列表在每个下标位置存放每个元素。由动态列表实现元素的随机返回。
63
63
64
64
注意,在 ` remove() ` 实现上,将列表的最后一个元素设置到待删元素的位置上,然后删除最后一个元素,这样在删除元素的时候,不需要挪动一大批元素,从而实现 ` O(1) ` 时间内操作。
65
65
66
+ 操作细节:
67
+
68
+ 1 . ** 插入**
69
+
70
+ 每次添加新数值时,先使用哈希表判断该数值是否存在,存在则直接返回 false。不存在则进行插入操作,只要将该数值添加到数组尾部即可,并将该数值和其下标的映射存入哈希表。
71
+
72
+ 2 . ** 删除**
73
+
74
+ 删除同样需使用哈希表判断是否存在,若不存在则返回 false。存在则进行删除操作,在哈希表中删除时间复杂度为 O(1),但是在数值中删除比较麻烦。若只是直接删除,则为了保证数组内存连续性需将删除数值后面的数值均前移一位,时间复杂度为 O(n)。比较好的处理方式是,用数组的最后一个数值去填充需要删除的数值的内存,其他数值在数组中的位置保持不变,并将这个拿来填充的数值的下标更新即可,最后只要删除数组最后一个数值,同样可以保证时间复杂度为 O(1)。
75
+
76
+ 3 . ** 随机返回**
77
+
78
+ 只要随机生成数组下标范围内一个随机下标值,返回该数组下标内的数值即可。
79
+
66
80
<!-- tabs:start -->
67
81
68
82
### ** Python3**
@@ -73,48 +87,36 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
73
87
class RandomizedSet :
74
88
75
89
def __init__ (self ):
76
- """
77
- Initialize your data structure here.
78
- """
79
90
self .m = {}
80
91
self .l = []
81
92
82
93
def insert (self , val : int ) -> bool :
83
- """
84
- Inserts a value to the set. Returns true if the set did not already contain the specified element.
85
- """
86
94
if val in self .m:
87
95
return False
88
96
self .m[val] = len (self .l)
89
97
self .l.append(val)
90
98
return True
91
99
92
100
def remove (self , val : int ) -> bool :
93
- """
94
- Removes a value from the set. Returns true if the set contained the specified element.
95
- """
96
101
if val not in self .m:
97
102
return False
98
103
idx = self .m[val]
99
- last_idx = len (self .l) - 1
100
- self .m[self .l[last_idx]] = idx
101
- self .m.pop(val)
102
- self .l[idx] = self .l[last_idx]
104
+ self .l[idx] = self .l[- 1 ]
105
+ self .m[self .l[- 1 ]] = idx
103
106
self .l.pop()
107
+ self .m.pop(val)
104
108
return True
105
109
106
110
def getRandom (self ) -> int :
107
- """
108
- Get a random element from the set.
109
- """
110
- return random.choice(self .l)
111
+ return choice(self .l)
111
112
112
113
113
114
# Your RandomizedSet object will be instantiated and called as such:
114
115
# obj = RandomizedSet()
115
116
# param_1 = obj.insert(val)
116
117
# param_2 = obj.remove(val)
117
118
# param_3 = obj.getRandom()
119
+
118
120
```
119
121
120
122
### ** Java**
@@ -123,18 +125,14 @@ class RandomizedSet:
123
125
124
126
``` java
125
127
class RandomizedSet {
126
- private Map<Integer , Integer > m;
127
- private List<Integer > l;
128
- private Random rnd;
128
+ private Map<Integer , Integer > m = new HashMap<> () ;
129
+ private List<Integer > l = new ArrayList<> () ;
130
+ private Random rnd = new Random () ;
129
131
130
- /* * Initialize your data structure here. */
131
132
public RandomizedSet () {
132
- m = new HashMap<> ();
133
- l = new ArrayList<> ();
134
- rnd = new Random ();
135
- }
136
133
137
- /* * Inserts a value to the set. Returns true if the set did not already contain the specified element. */
134
+ }
135
+
138
136
public boolean insert (int val ) {
139
137
if (m. containsKey(val)) {
140
138
return false ;
@@ -143,22 +141,19 @@ class RandomizedSet {
143
141
l. add(val);
144
142
return true ;
145
143
}
146
-
147
- /* * Removes a value from the set. Returns true if the set contained the specified element. */
144
+
148
145
public boolean remove (int val ) {
149
146
if (! m. containsKey(val)) {
150
147
return false ;
151
148
}
152
149
int idx = m. get(val);
153
- int lastIdx = l. size() - 1 ;
154
- m. put(l. get(lastIdx), idx);
150
+ l. set(idx, l. get(l. size() - 1 ));
151
+ m. put(l. get(l. size() - 1 ), idx);
152
+ l. remove(l. size() - 1 );
155
153
m. remove(val);
156
- l. set(idx, l. get(lastIdx));
157
- l. remove(lastIdx);
158
154
return true ;
159
155
}
160
-
161
- /* * Get a random element from the set. */
156
+
162
157
public int getRandom () {
163
158
int idx = rnd. nextInt(l. size());
164
159
return l. get(idx);
@@ -176,49 +171,33 @@ class RandomizedSet {
176
171
177
172
### ** C++**
178
173
179
- 1 . 插入
180
-
181
- 每次添加新数值时,先使用哈希表判断该数值是否存在,存在则直接返回 false。不存在则进行插入操作,只要将该数值添加到数组尾部即可,并将该数值和其下标的映射存入哈希表。
182
-
183
- 2 . 删除
184
-
185
- 删除同样需使用哈希表判断是否存在,若不存在则返回 false。存在则进行删除操作,在哈希表中删除时间复杂度为 O(1),但是在数值中删除比较麻烦。若只是直接删除,则为了保证数组内存连续性需将删除数值后面的数值均前移一位,时间复杂度为 O(n)。比较好的处理方式是,用数组的最后一个数值去填充需要删除的数值的内存,其他数值在数组中的位置保持不变,并将这个拿来填充的数值的下标更新即可,最后只要删除数组最后一个数值,同样可以保证时间复杂度为 O(1)。
186
-
187
- 3 . 随机返回
188
-
189
- 只要随机生成数组下标范围内一个随机下标值,返回该数组下标内的数值即可。
190
-
191
174
``` cpp
192
175
class RandomizedSet {
176
+ private:
193
177
unordered_map<int, int> mp;
194
178
vector<int > nums;
195
179
public:
196
180
RandomizedSet() {
197
181
198
182
}
199
-
183
+
200
184
bool insert (int val) {
201
- if (mp.count(val))
202
- return false;
203
-
185
+ if (mp.count(val)) return false;
204
186
mp[ val] = nums.size();
205
187
nums.push_back(val);
206
188
return true;
207
189
}
208
-
190
+
209
191
bool remove(int val) {
210
- if (!mp.count(val))
211
- return false;
212
-
213
- int removeIndex = mp[val];
214
- nums[removeIndex] = nums.back();
215
- mp[nums.back()] = removeIndex;
216
-
192
+ if (!mp.count(val)) return false;
193
+ int idx = mp[ val] ;
194
+ nums[ idx] = nums.back();
195
+ mp[ nums.back()] = idx;
217
196
mp.erase(val);
218
197
nums.pop_back();
219
198
return true;
220
199
}
221
-
200
+
222
201
int getRandom() {
223
202
return nums[ rand() % nums.size()] ;
224
203
}
@@ -233,6 +212,52 @@ public:
233
212
* /
234
213
```
235
214
215
+ ### **Go**
216
+
217
+ ```go
218
+ type RandomizedSet struct {
219
+ m map[int]int
220
+ l []int
221
+ }
222
+
223
+ func Constructor() RandomizedSet {
224
+ return RandomizedSet{map[int]int{}, []int{}}
225
+ }
226
+
227
+ func (this *RandomizedSet) Insert(val int) bool {
228
+ if _, ok := this.m[val]; ok {
229
+ return false
230
+ }
231
+ this.m[val] = len(this.l)
232
+ this.l = append(this.l, val)
233
+ return true
234
+ }
235
+
236
+ func (this *RandomizedSet) Remove(val int) bool {
237
+ if _, ok := this.m[val]; !ok {
238
+ return false
239
+ }
240
+ idx := this.m[val]
241
+ this.l[idx] = this.l[len(this.l)-1]
242
+ this.m[this.l[len(this.l)-1]] = idx
243
+ this.l = this.l[:len(this.l)-1]
244
+ delete(this.m, val)
245
+ return true
246
+ }
247
+
248
+ func (this *RandomizedSet) GetRandom() int {
249
+ return this.l[rand.Intn(len(this.l))]
250
+ }
251
+
252
+ /**
253
+ * Your RandomizedSet object will be instantiated and called as such:
254
+ * obj := Constructor();
255
+ * param_1 := obj.Insert(val);
256
+ * param_2 := obj.Remove(val);
257
+ * param_3 := obj.GetRandom();
258
+ */
259
+ ```
260
+
236
261
### ** ...**
237
262
238
263
```
0 commit comments