Skip to content

Commit 36e9d1b

Browse files
authored
Update 380. Insert Delete GetRandom O(1).md
1 parent 5ef7a8f commit 36e9d1b

File tree

1 file changed

+83
-98
lines changed

1 file changed

+83
-98
lines changed
Lines changed: 83 additions & 98 deletions
Original file line numberDiff line numberDiff line change
@@ -1,159 +1,144 @@
1-
### 380. Insert Delete GetRandom O(1)
1+
# 380. Insert Delete GetRandom O(1)
22

3+
**<font color=red>难度: Medium</font>**
34

5+
## 刷题内容
46

5-
题目:
6-
<https://leetcode.com/problems/insert-delete-getrandom-o1/>
7+
> 原题连接
78
9+
* https://leetcode.com/problems/insert-delete-getrandom-o1/description/
810

11+
> 内容描述
912
10-
难度 : Hard
13+
```
14+
Design a data structure that supports all following operations in average O(1) time.
1115
16+
insert(val): Inserts an item val to the set if not already present.
17+
remove(val): Removes an item val from the set if present.
18+
getRandom: Returns a random element from current set of elements. Each element must have the same probability of being returned.
19+
Example:
1220
21+
// Init an empty set.
22+
RandomizedSet randomSet = new RandomizedSet();
1323
14-
我的naive TLE代码,关键还是在想这个getRandom,这就不是O(1)的:
24+
// Inserts 1 to the set. Returns true as 1 was inserted successfully.
25+
randomSet.insert(1);
1526
27+
// Returns false as 2 does not exist in the set.
28+
randomSet.remove(2);
1629
30+
// Inserts 2 to the set, returns true. Set now contains [1,2].
31+
randomSet.insert(2);
1732
18-
```
19-
class RandomizedSet(object):
33+
// getRandom should return either 1 or 2 randomly.
34+
randomSet.getRandom();
2035
21-
def __init__(self):
22-
"""
23-
Initialize your data structure here.
24-
"""
25-
self.container = {}
26-
36+
// Removes 1 from the set, returns true. Set now contains [2].
37+
randomSet.remove(1);
2738
28-
def insert(self, val):
29-
"""
30-
Inserts a value to the set. Returns true if the set did not already contain the specified element.
31-
:type val: int
32-
:rtype: bool
33-
"""
34-
# 1 stands for present
35-
if val in self.container and self.container[val] == 1:
36-
return False
37-
else:
38-
self.container[val] = 1
39-
return True
40-
39+
// 2 was already in the set, so return false.
40+
randomSet.insert(2);
4141
42-
def remove(self, val):
43-
"""
44-
Removes a value from the set. Returns true if the set contained the specified element.
45-
:type val: int
46-
:rtype: bool
47-
"""
48-
if self.container.get(val,0) == 1:
49-
self.container[val] = 0
50-
return True
51-
else:
52-
return False
42+
// Since 2 is the only number in the set, getRandom always return 2.
43+
randomSet.getRandom();
44+
```
5345

54-
46+
## 解题方案
5547

56-
def getRandom(self):
57-
"""
58-
Get a random element from the set.
59-
:rtype: int
60-
"""
61-
import random
62-
keys = self.container.keys()
63-
rd = random.randint(0, len(keys) - 1)
64-
if self.container[keys[rd]] == 1:
65-
return keys[rd]
66-
elif self.container.get(keys[rd],0) == 0:
67-
return self.getRandom()
68-
```
48+
> 思路 1
49+
******- 时间复杂度: O(1)******- 空间复杂度: O(N)******
6950

7051

7152

72-
也是有[stackoverflow问题界面的题目](http://stackoverflow.com/questions/5682218/data-structure-insert-remove-contains-get-random-element-all-at-o1#comment18171331_5684892)
53+
因为对于插入,删除还有同可能性返回数都要O(1),我们知道以下几种典型的数据结构
54+
```
55+
dictionary
56+
list
57+
set
58+
LinkedList
59+
```
60+
想要删除确定数字必须要知道数字的index,所以list肯定需要,然后怎么通过O(1)时间得到要删除元素的index呢?
61+
就想到用字典,key,value分别是element和其index
7362

74-
> Consider a data structure composed of a hashtable H and an array A. The hashtable keys are the elements in the data structure, and the values are their positions in the array.
75-
>
76-
> 1.insert(value): append the value to array and let i be its index in A. Set H[value]=i.
77-
>
78-
> 2.remove(value): We are going to replace the cell that contains value in A with the last element in A. let d be the last element in the array A at index m. let i be H[value], the index in the array of the value to be removed. Set A[i]=d, H[d]=i, decrease the size of the array by one, and remove value from H.
79-
>
80-
> 3.contains(value): return H.contains(value)
81-
>
82-
> 4.getRandomElement(): let r=random(current size of A). return A[r].
83-
>
84-
>
85-
>
86-
> since the array needs to auto-increase in size, it's going to be amortize O(1) to add an element, but I guess that's OK.
63+
然后想要O(1)时间同可能性返回数都要,必须要知道总共有多少个数字,那么就要维护一个self.length才行
8764

8865

8966

9067

9168

92-
按照以答案AC代码
9369

94-
```
70+
```python
71+
import random
9572
class RandomizedSet(object):
9673

9774
def __init__(self):
9875
"""
9976
Initialize your data structure here.
10077
"""
101-
self.hashtable = {}
102-
self.array = []
103-
self.arraySize = 0
78+
self.cache = {}
79+
self.lst = []
80+
self.length = 0
81+
10482

10583
def insert(self, val):
10684
"""
10785
Inserts a value to the set. Returns true if the set did not already contain the specified element.
10886
:type val: int
10987
:rtype: bool
11088
"""
111-
# already in the set
112-
if val in self.hashtable:
113-
return False
114-
else:
115-
self.hashtable[val] = self.arraySize
116-
self.array.append(val)
117-
self.arraySize += 1
89+
# if this element is not in our RandomizedSet
90+
if val not in self.cache:
91+
# just insert into both of our self.cache and self.lst
92+
self.cache[val] = self.length
93+
self.lst.append(val)
94+
self.length += 1
11895
return True
119-
96+
else:
97+
return False
98+
12099

121100
def remove(self, val):
122101
"""
123102
Removes a value from the set. Returns true if the set contained the specified element.
124103
:type val: int
125104
:rtype: bool
126105
"""
127-
if val not in self.hashtable:
128-
return False
129-
else:
130-
removeIdx = self.hashtable[val]
131-
if self.arraySize == 1:
132-
self.__init__()
133-
else:
134-
self.array[removeIdx] = self.array[-1]
135-
self.hashtable[self.array[-1]] = removeIdx
136-
self.arraySize -= 1
137-
del self.hashtable[val]
138-
del self.array[-1]
106+
# if the elment is in our RandomizedSet
107+
if val in self.cache:
108+
# get the index of element in our self.lst
109+
idx = self.cache[val]
110+
# use the index to update our self.lst
111+
self.lst[idx] = self.lst[-1] # swap the value in index and self.length-1
112+
# this should be done before pop() operation
113+
# because we may only have one element is self.lst
114+
self.cache[self.lst[idx]] = idx
115+
self.lst.pop()
116+
del self.cache[val]
117+
self.length -= 1
139118
return True
119+
else:
120+
return False
140121

141122

142-
143123
def getRandom(self):
144124
"""
145125
Get a random element from the set.
146126
:rtype: int
147127
"""
148-
import random
149-
rd = random.randint(0, self.arraySize-1)
150-
return self.array[rd]
151-
```
152-
128+
# 这种是常规方法
129+
# idx = random.randint(0, self.length-1)
130+
# return self.lst[idx]
131+
# 神奇函数
132+
return random.choice(self.lst)
133+
153134

154135

136+
# Your RandomizedSet object will be instantiated and called as such:
137+
# obj = RandomizedSet()
138+
# param_1 = obj.insert(val)
139+
# param_2 = obj.remove(val)
140+
# param_3 = obj.getRandom()
141+
```
155142

156143

157-
最后getRandom也可以写成:
158144

159-
`return random.choice(self.array)`

0 commit comments

Comments
 (0)