Skip to content

Commit 4e3c726

Browse files
committedFeb 3, 2023
feat: add solutions to lcof problem: No.41
No.1145.Binary Tree Coloring Game
1 parent 5d5c697 commit 4e3c726

File tree

7 files changed

+128
-92
lines changed

7 files changed

+128
-92
lines changed
 

‎lcof/面试题41. 数据流中的中位数/README.md

+73-44
Original file line numberDiff line numberDiff line change
@@ -48,17 +48,15 @@
4848

4949
<!-- 这里可写通用的实现逻辑 -->
5050

51-
**方法一:优先队列(双堆**
51+
**方法一:优先队列(大小根堆**
5252

53-
创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素
53+
我们可以维护两个优先队列,一个大根堆,一个小根堆,大根堆存储较小的一半数,小根堆存储较大的一半数
5454

55-
添加元素时,先放入小根堆,然后将小根堆对顶元素弹出并放入大根堆(使得大根堆个数多 $1$);若大小根堆元素个数差超过 $1$,则将大根堆元素弹出放入小根堆
55+
当两个堆的元素个数相同时,我们优先往小根堆中添加元素,这样会使得小根堆元素个数比大根堆多 $1$,这样中位数就可以从小根堆中取出
5656

57-
取中位数时,若大根堆元素较多,取大根堆堆顶,否则取两堆顶元素和的平均值
57+
当两个堆的元素个数不同时,说明此时小根堆元素个数比大根堆多 $1$,我们往大根堆中添加元素,这样会使得两个堆元素个数相同,这样中位数就可以从两个堆中取出
5858

59-
**时间复杂度分析:**
60-
61-
每次添加元素的时间复杂度为 $O(\log n)$,取中位数的时间复杂度为 $O(1)$。
59+
时间复杂度方面,添加元素的时间复杂度为 $O(\log n)$,查找中位数的时间复杂度为 $O(1)$。空间复杂度为 $O(n)$。其中 $n$ 为数据流中元素的个数。
6260

6361
<!-- tabs:start -->
6462

@@ -68,24 +66,50 @@
6866

6967
```python
7068
class MedianFinder:
69+
def __init__(self):
70+
"""
71+
initialize your data structure here.
72+
"""
73+
self.q1 = []
74+
self.q2 = []
75+
76+
def addNum(self, num: int) -> None:
77+
if len(self.q1) > len(self.q2):
78+
heappush(self.q2, -heappushpop(self.q1, num))
79+
else:
80+
heappush(self.q1, -heappushpop(self.q2, -num))
81+
82+
def findMedian(self) -> float:
83+
if len(self.q1) > len(self.q2):
84+
return self.q1[0]
85+
return (self.q1[0] - self.q2[0]) / 2
86+
87+
88+
# Your MedianFinder object will be instantiated and called as such:
89+
# obj = MedianFinder()
90+
# obj.addNum(num)
91+
# param_2 = obj.findMedian()
92+
```
93+
94+
```python
95+
from sortedcontainers import SortedList
7196

97+
98+
class MedianFinder:
7299
def __init__(self):
73100
"""
74101
initialize your data structure here.
75102
"""
76-
self.h1 = []
77-
self.h2 = []
103+
self.sl = SortedList()
78104

79105
def addNum(self, num: int) -> None:
80-
heappush(self.h1, num)
81-
heappush(self.h2, -heappop(self.h1))
82-
if len(self.h2) - len(self.h1) > 1:
83-
heappush(self.h1, -heappop(self.h2))
106+
self.sl.add(num)
84107

85108
def findMedian(self) -> float:
86-
if len(self.h2) > len(self.h1):
87-
return -self.h2[0]
88-
return (self.h1[0] - self.h2[0]) / 2
109+
n = len(self.sl)
110+
if n & 1:
111+
return self.sl[n // 2]
112+
return (self.sl[(n - 1) // 2] + self.sl[n // 2]) / 2
89113

90114

91115
# Your MedianFinder object will be instantiated and called as such:
@@ -101,26 +125,28 @@ class MedianFinder:
101125
```java
102126
class MedianFinder {
103127
private PriorityQueue<Integer> q1 = new PriorityQueue<>();
104-
private PriorityQueue<Integer> q2 = new PriorityQueue<>(Collections.reverseOrder());
128+
private PriorityQueue<Integer> q2 = new PriorityQueue<>((a, b) -> b - a);
105129

106130
/** initialize your data structure here. */
107131
public MedianFinder() {
108132

109133
}
110134

111135
public void addNum(int num) {
112-
q1.offer(num);
113-
q2.offer(q1.poll());
114-
if (q2.size() - q1.size() > 1) {
136+
if (q1.size() > q2.size()) {
137+
q1.offer(num);
138+
q2.offer(q1.poll());
139+
} else {
140+
q2.offer(num);
115141
q1.offer(q2.poll());
116142
}
117143
}
118144

119145
public double findMedian() {
120-
if (q2.size() > q1.size()) {
121-
return q2.peek();
146+
if (q1.size() > q2.size()) {
147+
return q1.peek();
122148
}
123-
return (q1.peek() + q2.peek()) * 1.0 / 2;
149+
return (q1.peek() + q2.peek()) / 2.0;
124150
}
125151
}
126152

@@ -143,20 +169,22 @@ public:
143169
}
144170

145171
void addNum(int num) {
146-
q1.push(num);
147-
q2.push(q1.top());
148-
q1.pop();
149-
if (q2.size() - q1.size() > 1) {
172+
if (q1.size() > q2.size()) {
173+
q1.push(num);
174+
q2.push(q1.top());
175+
q1.pop();
176+
} else {
177+
q2.push(num);
150178
q1.push(q2.top());
151179
q2.pop();
152180
}
153181
}
154182

155183
double findMedian() {
156-
if (q2.size() > q1.size()) {
157-
return q2.top();
184+
if (q1.size() > q2.size()) {
185+
return q1.top();
158186
}
159-
return (double) (q1.top() + q2.top()) / 2;
187+
return (q1.top() + q2.top()) / 2.0;
160188
}
161189

162190
private:
@@ -176,8 +204,7 @@ private:
176204
177205
```go
178206
type MedianFinder struct {
179-
q1 hp
180-
q2 hp
207+
q1, q2 hp
181208
}
182209
183210
/** initialize your data structure here. */
@@ -186,27 +213,22 @@ func Constructor() MedianFinder {
186213
}
187214
188215
func (this *MedianFinder) AddNum(num int) {
189-
heap.Push(&this.q1, num)
190-
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
191-
if this.q2.Len()-this.q1.Len() > 1 {
216+
if this.q1.Len() > this.q2.Len() {
217+
heap.Push(&this.q1, num)
218+
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
219+
} else {
220+
heap.Push(&this.q2, -num)
192221
heap.Push(&this.q1, -heap.Pop(&this.q2).(int))
193222
}
194223
}
195224
196225
func (this *MedianFinder) FindMedian() float64 {
197-
if this.q2.Len() > this.q1.Len() {
198-
return -float64(this.q2.IntSlice[0])
226+
if this.q1.Len() > this.q2.Len() {
227+
return float64(this.q1.IntSlice[0])
199228
}
200229
return float64(this.q1.IntSlice[0]-this.q2.IntSlice[0]) / 2.0
201230
}
202231
203-
/**
204-
* Your MedianFinder object will be instantiated and called as such:
205-
* obj := Constructor();
206-
* obj.AddNum(num);
207-
* param_2 := obj.FindMedian();
208-
*/
209-
210232
type hp struct{ sort.IntSlice }
211233
212234
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
@@ -217,6 +239,13 @@ func (h *hp) Pop() interface{} {
217239
h.IntSlice = a[:len(a)-1]
218240
return v
219241
}
242+
243+
/**
244+
* Your MedianFinder object will be instantiated and called as such:
245+
* obj := Constructor();
246+
* obj.AddNum(num);
247+
* param_2 := obj.FindMedian();
248+
*/
220249
```
221250

222251
### **JavaScript**

‎lcof/面试题41. 数据流中的中位数/Solution.cpp

+9-7
Original file line numberDiff line numberDiff line change
@@ -6,20 +6,22 @@ class MedianFinder {
66
}
77

88
void addNum(int num) {
9-
q1.push(num);
10-
q2.push(q1.top());
11-
q1.pop();
12-
if (q2.size() - q1.size() > 1) {
9+
if (q1.size() > q2.size()) {
10+
q1.push(num);
11+
q2.push(q1.top());
12+
q1.pop();
13+
} else {
14+
q2.push(num);
1315
q1.push(q2.top());
1416
q2.pop();
1517
}
1618
}
1719

1820
double findMedian() {
19-
if (q2.size() > q1.size()) {
20-
return q2.top();
21+
if (q1.size() > q2.size()) {
22+
return q1.top();
2123
}
22-
return (double) (q1.top() + q2.top()) / 2;
24+
return (q1.top() + q2.top()) / 2.0;
2325
}
2426

2527
private:
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
type MedianFinder struct {
2-
q1 hp
3-
q2 hp
2+
q1, q2 hp
43
}
54

65
/** initialize your data structure here. */
@@ -9,27 +8,22 @@ func Constructor() MedianFinder {
98
}
109

1110
func (this *MedianFinder) AddNum(num int) {
12-
heap.Push(&this.q1, num)
13-
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
14-
if this.q2.Len()-this.q1.Len() > 1 {
11+
if this.q1.Len() > this.q2.Len() {
12+
heap.Push(&this.q1, num)
13+
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
14+
} else {
15+
heap.Push(&this.q2, -num)
1516
heap.Push(&this.q1, -heap.Pop(&this.q2).(int))
1617
}
1718
}
1819

1920
func (this *MedianFinder) FindMedian() float64 {
20-
if this.q2.Len() > this.q1.Len() {
21-
return -float64(this.q2.IntSlice[0])
21+
if this.q1.Len() > this.q2.Len() {
22+
return float64(this.q1.IntSlice[0])
2223
}
2324
return float64(this.q1.IntSlice[0]-this.q2.IntSlice[0]) / 2.0
2425
}
2526

26-
/**
27-
* Your MedianFinder object will be instantiated and called as such:
28-
* obj := Constructor();
29-
* obj.AddNum(num);
30-
* param_2 := obj.FindMedian();
31-
*/
32-
3327
type hp struct{ sort.IntSlice }
3428

3529
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
@@ -39,4 +33,11 @@ func (h *hp) Pop() interface{} {
3933
v := a[len(a)-1]
4034
h.IntSlice = a[:len(a)-1]
4135
return v
42-
}
36+
}
37+
38+
/**
39+
* Your MedianFinder object will be instantiated and called as such:
40+
* obj := Constructor();
41+
* obj.AddNum(num);
42+
* param_2 := obj.FindMedian();
43+
*/

‎lcof/面试题41. 数据流中的中位数/Solution.java

+9-7
Original file line numberDiff line numberDiff line change
@@ -1,25 +1,27 @@
11
class MedianFinder {
22
private PriorityQueue<Integer> q1 = new PriorityQueue<>();
3-
private PriorityQueue<Integer> q2 = new PriorityQueue<>(Collections.reverseOrder());
3+
private PriorityQueue<Integer> q2 = new PriorityQueue<>((a, b) -> b - a);
44

55
/** initialize your data structure here. */
66
public MedianFinder() {
77

88
}
99

1010
public void addNum(int num) {
11-
q1.offer(num);
12-
q2.offer(q1.poll());
13-
if (q2.size() - q1.size() > 1) {
11+
if (q1.size() > q2.size()) {
12+
q1.offer(num);
13+
q2.offer(q1.poll());
14+
} else {
15+
q2.offer(num);
1416
q1.offer(q2.poll());
1517
}
1618
}
1719

1820
public double findMedian() {
19-
if (q2.size() > q1.size()) {
20-
return q2.peek();
21+
if (q1.size() > q2.size()) {
22+
return q1.peek();
2123
}
22-
return (q1.peek() + q2.peek()) * 1.0 / 2;
24+
return (q1.peek() + q2.peek()) / 2.0;
2325
}
2426
}
2527

‎lcof/面试题41. 数据流中的中位数/Solution.py

+9-9
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,19 @@ def __init__(self):
33
"""
44
initialize your data structure here.
55
"""
6-
self.h1 = []
7-
self.h2 = []
6+
self.q1 = []
7+
self.q2 = []
88

99
def addNum(self, num: int) -> None:
10-
heappush(self.h1, num)
11-
heappush(self.h2, -heappop(self.h1))
12-
if len(self.h2) - len(self.h1) > 1:
13-
heappush(self.h1, -heappop(self.h2))
10+
if len(self.q1) > len(self.q2):
11+
heappush(self.q2, -heappushpop(self.q1, num))
12+
else:
13+
heappush(self.q1, -heappushpop(self.q2, -num))
1414

1515
def findMedian(self) -> float:
16-
if len(self.h2) > len(self.h1):
17-
return -self.h2[0]
18-
return (self.h1[0] - self.h2[0]) / 2
16+
if len(self.q1) > len(self.q2):
17+
return self.q1[0]
18+
return (self.q1[0] - self.q2[0]) / 2
1919

2020

2121
# Your MedianFinder object will be instantiated and called as such:

‎solution/1100-1199/1145.Binary Tree Coloring Game/README.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -195,23 +195,24 @@ func btreeGameWinningMove(root *TreeNode, n int, x int) bool {
195195
if root == nil || root.Val == x {
196196
return root
197197
}
198-
l := dfs(root.Left)
199-
if l != nil {
200-
return l
198+
node := dfs(root.Left)
199+
if node != nil {
200+
return node
201201
}
202202
return dfs(root.Right)
203203
}
204+
204205
var count func(*TreeNode) int
205206
count = func(root *TreeNode) int {
206207
if root == nil {
207208
return 0
208209
}
209210
return 1 + count(root.Left) + count(root.Right)
210211
}
212+
211213
node := dfs(root)
212214
l, r := count(node.Left), count(node.Right)
213-
m := max(max(l, r), n-l-r-1)
214-
return m > n-m
215+
return max(max(l, r), n-l-r-1) > n/2
215216
}
216217
217218
func max(a, b int) int {

‎solution/1100-1199/1145.Binary Tree Coloring Game/README_EN.md

+6-5
Original file line numberDiff line numberDiff line change
@@ -170,23 +170,24 @@ func btreeGameWinningMove(root *TreeNode, n int, x int) bool {
170170
if root == nil || root.Val == x {
171171
return root
172172
}
173-
l := dfs(root.Left)
174-
if l != nil {
175-
return l
173+
node := dfs(root.Left)
174+
if node != nil {
175+
return node
176176
}
177177
return dfs(root.Right)
178178
}
179+
179180
var count func(*TreeNode) int
180181
count = func(root *TreeNode) int {
181182
if root == nil {
182183
return 0
183184
}
184185
return 1 + count(root.Left) + count(root.Right)
185186
}
187+
186188
node := dfs(root)
187189
l, r := count(node.Left), count(node.Right)
188-
m := max(max(l, r), n-l-r-1)
189-
return m > n-m
190+
return max(max(l, r), n-l-r-1) > n/2
190191
}
191192
192193
func max(a, b int) int {

0 commit comments

Comments
 (0)
Please sign in to comment.