Skip to content

Navigation Menu

Sign in
Appearance settings

Search code, repositories, users, issues, pull requests...

Provide feedback

We read every piece of feedback, and take your input very seriously.

Saved searches

Use saved searches to filter your results more quickly

Sign up
Appearance settings

Commit 4352b31

Browse files
committed
feat: add solutions to lc problem: No.0380
No.0380.Insert Delete GetRandom O(1)
1 parent 04924f4 commit 4352b31

File tree

6 files changed

+277
-216
lines changed

6 files changed

+277
-216
lines changed

‎solution/0300-0399/0380.Insert Delete GetRandom O(1)/README.md‎

Lines changed: 85 additions & 60 deletions
Original file line numberDiff line numberDiff line change
@@ -57,12 +57,26 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
5757

5858
<!-- 这里可写通用的实现逻辑 -->
5959

60-
"哈希表 + 动态列表"实现。
60+
**方法一:哈希表 + 动态列表**
6161

6262
哈希表存放每个元素的值和对应的下标,而动态列表在每个下标位置存放每个元素。由动态列表实现元素的随机返回。
6363

6464
注意,在 `remove()` 实现上,将列表的最后一个元素设置到待删元素的位置上,然后删除最后一个元素,这样在删除元素的时候,不需要挪动一大批元素,从而实现 `O(1)` 时间内操作。
6565

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+
6680
<!-- tabs:start -->
6781

6882
### **Python3**
@@ -73,48 +87,36 @@ randomizedSet.getRandom(); // 由于 2 是集合中唯一的数字,getRandom
7387
class RandomizedSet:
7488

7589
def __init__(self):
76-
"""
77-
Initialize your data structure here.
78-
"""
7990
self.m = {}
8091
self.l = []
8192

8293
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-
"""
8694
if val in self.m:
8795
return False
8896
self.m[val] = len(self.l)
8997
self.l.append(val)
9098
return True
9199

92100
def remove(self, val: int) -> bool:
93-
"""
94-
Removes a value from the set. Returns true if the set contained the specified element.
95-
"""
96101
if val not in self.m:
97102
return False
98103
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
103106
self.l.pop()
107+
self.m.pop(val)
104108
return True
105109

106110
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)
111112

112113

113114
# Your RandomizedSet object will be instantiated and called as such:
114115
# obj = RandomizedSet()
115116
# param_1 = obj.insert(val)
116117
# param_2 = obj.remove(val)
117118
# param_3 = obj.getRandom()
119+
118120
```
119121

120122
### **Java**
@@ -123,18 +125,14 @@ class RandomizedSet:
123125

124126
```java
125127
class RandomizedSet {
126-
private Map<Integer, Integer> m;
127-
private List<Integer> l;
128-
private Random rnd;
128+
private Map<Integer, Integer> m=newHashMap<>();
129+
private List<Integer> l=newArrayList<>();
130+
private Random rnd=newRandom();
129131

130-
/** Initialize your data structure here. */
131132
public RandomizedSet() {
132-
m = new HashMap<>();
133-
l = new ArrayList<>();
134-
rnd = new Random();
135-
}
136133

137-
/** Inserts a value to the set. Returns true if the set did not already contain the specified element. */
134+
}
135+
138136
public boolean insert(int val) {
139137
if (m.containsKey(val)) {
140138
return false;
@@ -143,22 +141,19 @@ class RandomizedSet {
143141
l.add(val);
144142
return true;
145143
}
146-
147-
/** Removes a value from the set. Returns true if the set contained the specified element. */
144+
148145
public boolean remove(int val) {
149146
if (!m.containsKey(val)) {
150147
return false;
151148
}
152149
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);
155153
m.remove(val);
156-
l.set(idx, l.get(lastIdx));
157-
l.remove(lastIdx);
158154
return true;
159155
}
160-
161-
/** Get a random element from the set. */
156+
162157
public int getRandom() {
163158
int idx = rnd.nextInt(l.size());
164159
return l.get(idx);
@@ -176,49 +171,33 @@ class RandomizedSet {
176171

177172
### **C++**
178173

179-
1. 插入
180-
181-
每次添加新数值时,先使用哈希表判断该数值是否存在,存在则直接返回 false。不存在则进行插入操作,只要将该数值添加到数组尾部即可,并将该数值和其下标的映射存入哈希表。
182-
183-
2. 删除
184-
185-
删除同样需使用哈希表判断是否存在,若不存在则返回 false。存在则进行删除操作,在哈希表中删除时间复杂度为 O(1),但是在数值中删除比较麻烦。若只是直接删除,则为了保证数组内存连续性需将删除数值后面的数值均前移一位,时间复杂度为 O(n)。比较好的处理方式是,用数组的最后一个数值去填充需要删除的数值的内存,其他数值在数组中的位置保持不变,并将这个拿来填充的数值的下标更新即可,最后只要删除数组最后一个数值,同样可以保证时间复杂度为 O(1)。
186-
187-
3. 随机返回
188-
189-
只要随机生成数组下标范围内一个随机下标值,返回该数组下标内的数值即可。
190-
191174
```cpp
192175
class RandomizedSet {
176+
private:
193177
unordered_map<int, int> mp;
194178
vector<int> nums;
195179
public:
196180
RandomizedSet() {
197181

198182
}
199-
183+
200184
bool insert(int val) {
201-
if (mp.count(val))
202-
return false;
203-
185+
if (mp.count(val)) return false;
204186
mp[val] = nums.size();
205187
nums.push_back(val);
206188
return true;
207189
}
208-
190+
209191
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;
217196
mp.erase(val);
218197
nums.pop_back();
219198
return true;
220199
}
221-
200+
222201
int getRandom() {
223202
return nums[rand() % nums.size()];
224203
}
@@ -233,6 +212,52 @@ public:
233212
*/
234213
```
235214
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+
236261
### **...**
237262

238263
```

0 commit comments

Comments
(0)

AltStyle によって変換されたページ (->オリジナル) /