Skip to content

Commit 21216cc

Browse files
committed
feat: add solutions to lc/lcci/lcof problems
Continuous Median
1 parent 932cc5a commit 21216cc

File tree

24 files changed

+1347
-332
lines changed

24 files changed

+1347
-332
lines changed

lcci/17.19.Missing Two/README.md

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@
3535

3636
1. 对于任何数 $x$,都有 $x \oplus x = 0$
3737
1. 异或运算满足结合律,即 $(a \oplus b) \oplus c = a \oplus (b \oplus c)$
38-
1. lowbit 运算获取最低一位的 $1$ 及其后面的所有 $0$,公式为 $lowbit(x) = x \& (-x)$
38+
1. lowbit 运算获取最低一位的 $1$ 及其后面的所有 $0$,公式为 `lowbit(x) = x & (-x)`
3939

4040
我们将 nums 中所有数进行异或到 $x$,再将 $[1,2..n]$ 的所有数也异或到 $x$。得到的 $x$ 是两个缺失的正整数的异或和。
4141

lcci/17.20.Continuous Median/README.md

+118-23
Original file line numberDiff line numberDiff line change
@@ -35,9 +35,17 @@ findMedian() -> 2
3535

3636
<!-- 这里可写通用的实现逻辑 -->
3737

38-
- 创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素。
39-
- 添加元素时,先放入小根堆,然后将小根堆对顶元素弹出并放入大根堆(使得大根堆个数多 1);若大小根堆元素个数差超过 1,则将大根堆元素弹出放入小根堆。
40-
- 取中位数时,若大根堆元素较多,取大根堆堆顶,否则取两堆顶元素和的平均值。
38+
**方法一:优先队列(双堆)**
39+
40+
创建大根堆、小根堆,其中:大根堆存放较小的一半元素,小根堆存放较大的一半元素。
41+
42+
添加元素时,先放入小根堆,然后将小根堆对顶元素弹出并放入大根堆(使得大根堆个数多 $1$);若大小根堆元素个数差超过 $1$,则将大根堆元素弹出放入小根堆。
43+
44+
取中位数时,若大根堆元素较多,取大根堆堆顶,否则取两堆顶元素和的平均值。
45+
46+
**时间复杂度分析:**
47+
48+
每次添加元素的时间复杂度为 $O(\log n)$,取中位数的时间复杂度为 $O(1)$。
4149

4250
<!-- tabs:start -->
4351

@@ -47,23 +55,24 @@ findMedian() -&gt; 2
4755

4856
```python
4957
class MedianFinder:
58+
5059
def __init__(self):
5160
"""
5261
initialize your data structure here.
5362
"""
54-
self.min_heap = []
55-
self.max_heap = []
63+
self.h1 = []
64+
self.h2 = []
5665

5766
def addNum(self, num: int) -> None:
58-
heappush(self.min_heap, num)
59-
heappush(self.max_heap, -heappop(self.min_heap))
60-
if len(self.max_heap) - len(self.min_heap) > 1:
61-
heappush(self.min_heap, -heappop(self.max_heap))
67+
heappush(self.h1, num)
68+
heappush(self.h2, -heappop(self.h1))
69+
if len(self.h2) - len(self.h1) > 1:
70+
heappush(self.h1, -heappop(self.h2))
6271

6372
def findMedian(self) -> float:
64-
if len(self.max_heap) > len(self.min_heap):
65-
return -self.max_heap[0]
66-
return (self.min_heap[0] - self.max_heap[0]) / 2
73+
if len(self.h2) > len(self.h1):
74+
return -self.h2[0]
75+
return (self.h1[0] - self.h2[0]) / 2
6776

6877

6978
# Your MedianFinder object will be instantiated and called as such:
@@ -78,28 +87,27 @@ class MedianFinder:
7887

7988
```java
8089
class MedianFinder {
81-
private PriorityQueue<Integer> minHeap;
82-
private PriorityQueue<Integer> maxHeap;
90+
private PriorityQueue<Integer> q1 = new PriorityQueue<>();
91+
private PriorityQueue<Integer> q2 = new PriorityQueue<>(Collections.reverseOrder());
8392

8493
/** initialize your data structure here. */
8594
public MedianFinder() {
86-
minHeap = new PriorityQueue<>();
87-
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
95+
8896
}
8997

9098
public void addNum(int num) {
91-
minHeap.offer(num);
92-
maxHeap.offer(minHeap.poll());
93-
if (maxHeap.size() - minHeap.size() > 1) {
94-
minHeap.offer(maxHeap.poll());
99+
q1.offer(num);
100+
q2.offer(q1.poll());
101+
if (q2.size() - q1.size() > 1) {
102+
q1.offer(q2.poll());
95103
}
96104
}
97105

98106
public double findMedian() {
99-
if (maxHeap.size() > minHeap.size()) {
100-
return maxHeap.peek();
107+
if (q2.size() > q1.size()) {
108+
return q2.peek();
101109
}
102-
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
110+
return (q1.peek() + q2.peek()) * 1.0 / 2;
103111
}
104112
}
105113

@@ -111,6 +119,93 @@ class MedianFinder {
111119
*/
112120
```
113121

122+
### **C++**
123+
124+
```cpp
125+
class MedianFinder {
126+
public:
127+
/** initialize your data structure here. */
128+
MedianFinder() {
129+
130+
}
131+
132+
void addNum(int num) {
133+
q1.push(num);
134+
q2.push(q1.top());
135+
q1.pop();
136+
if (q2.size() - q1.size() > 1) {
137+
q1.push(q2.top());
138+
q2.pop();
139+
}
140+
}
141+
142+
double findMedian() {
143+
if (q2.size() > q1.size()) {
144+
return q2.top();
145+
}
146+
return (double) (q1.top() + q2.top()) / 2;
147+
}
148+
149+
private:
150+
priority_queue<int, vector<int>, greater<int>> q1;
151+
priority_queue<int> q2;
152+
};
153+
154+
/**
155+
* Your MedianFinder object will be instantiated and called as such:
156+
* MedianFinder* obj = new MedianFinder();
157+
* obj->addNum(num);
158+
* double param_2 = obj->findMedian();
159+
*/
160+
```
161+
162+
### **Go**
163+
164+
```go
165+
type MedianFinder struct {
166+
q1 hp
167+
q2 hp
168+
}
169+
170+
/** initialize your data structure here. */
171+
func Constructor() MedianFinder {
172+
return MedianFinder{hp{}, hp{}}
173+
}
174+
175+
func (this *MedianFinder) AddNum(num int) {
176+
heap.Push(&this.q1, num)
177+
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
178+
if this.q2.Len()-this.q1.Len() > 1 {
179+
heap.Push(&this.q1, -heap.Pop(&this.q2).(int))
180+
}
181+
}
182+
183+
func (this *MedianFinder) FindMedian() float64 {
184+
if this.q2.Len() > this.q1.Len() {
185+
return -float64(this.q2.IntSlice[0])
186+
}
187+
return float64(this.q1.IntSlice[0]-this.q2.IntSlice[0]) / 2.0
188+
}
189+
190+
/**
191+
* Your MedianFinder object will be instantiated and called as such:
192+
* obj := Constructor();
193+
* obj.AddNum(num);
194+
* param_2 := obj.FindMedian();
195+
*/
196+
197+
type hp struct{ sort.IntSlice }
198+
199+
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
200+
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
201+
func (h *hp) Pop() interface{} {
202+
a := h.IntSlice
203+
v := a[len(a)-1]
204+
h.IntSlice = a[:len(a)-1]
205+
return v
206+
}
207+
```
208+
114209
### **...**
115210

116211
```

lcci/17.20.Continuous Median/README_EN.md

+109-22
Original file line numberDiff line numberDiff line change
@@ -45,23 +45,24 @@ findMedian() -&gt; 2
4545

4646
```python
4747
class MedianFinder:
48+
4849
def __init__(self):
4950
"""
5051
initialize your data structure here.
5152
"""
52-
self.min_heap = []
53-
self.max_heap = []
53+
self.h1 = []
54+
self.h2 = []
5455

5556
def addNum(self, num: int) -> None:
56-
heappush(self.min_heap, num)
57-
heappush(self.max_heap, -heappop(self.min_heap))
58-
if len(self.max_heap) - len(self.min_heap) > 1:
59-
heappush(self.min_heap, -heappop(self.max_heap))
57+
heappush(self.h1, num)
58+
heappush(self.h2, -heappop(self.h1))
59+
if len(self.h2) - len(self.h1) > 1:
60+
heappush(self.h1, -heappop(self.h2))
6061

6162
def findMedian(self) -> float:
62-
if len(self.max_heap) > len(self.min_heap):
63-
return -self.max_heap[0]
64-
return (self.min_heap[0] - self.max_heap[0]) / 2
63+
if len(self.h2) > len(self.h1):
64+
return -self.h2[0]
65+
return (self.h1[0] - self.h2[0]) / 2
6566

6667

6768
# Your MedianFinder object will be instantiated and called as such:
@@ -74,28 +75,27 @@ class MedianFinder:
7475

7576
```java
7677
class MedianFinder {
77-
private PriorityQueue<Integer> minHeap;
78-
private PriorityQueue<Integer> maxHeap;
78+
private PriorityQueue<Integer> q1 = new PriorityQueue<>();
79+
private PriorityQueue<Integer> q2 = new PriorityQueue<>(Collections.reverseOrder());
7980

8081
/** initialize your data structure here. */
8182
public MedianFinder() {
82-
minHeap = new PriorityQueue<>();
83-
maxHeap = new PriorityQueue<>(Collections.reverseOrder());
84-
}
8583

84+
}
85+
8686
public void addNum(int num) {
87-
minHeap.offer(num);
88-
maxHeap.offer(minHeap.poll());
89-
if (maxHeap.size() - minHeap.size() > 1) {
90-
minHeap.offer(maxHeap.poll());
87+
q1.offer(num);
88+
q2.offer(q1.poll());
89+
if (q2.size() - q1.size() > 1) {
90+
q1.offer(q2.poll());
9191
}
9292
}
93-
93+
9494
public double findMedian() {
95-
if (maxHeap.size() > minHeap.size()) {
96-
return maxHeap.peek();
95+
if (q2.size() > q1.size()) {
96+
return q2.peek();
9797
}
98-
return (minHeap.peek() + maxHeap.peek()) * 1.0 / 2;
98+
return (q1.peek() + q2.peek()) * 1.0 / 2;
9999
}
100100
}
101101

@@ -107,6 +107,93 @@ class MedianFinder {
107107
*/
108108
```
109109

110+
### **C++**
111+
112+
```cpp
113+
class MedianFinder {
114+
public:
115+
/** initialize your data structure here. */
116+
MedianFinder() {
117+
118+
}
119+
120+
void addNum(int num) {
121+
q1.push(num);
122+
q2.push(q1.top());
123+
q1.pop();
124+
if (q2.size() - q1.size() > 1) {
125+
q1.push(q2.top());
126+
q2.pop();
127+
}
128+
}
129+
130+
double findMedian() {
131+
if (q2.size() > q1.size()) {
132+
return q2.top();
133+
}
134+
return (double) (q1.top() + q2.top()) / 2;
135+
}
136+
137+
private:
138+
priority_queue<int, vector<int>, greater<int>> q1;
139+
priority_queue<int> q2;
140+
};
141+
142+
/**
143+
* Your MedianFinder object will be instantiated and called as such:
144+
* MedianFinder* obj = new MedianFinder();
145+
* obj->addNum(num);
146+
* double param_2 = obj->findMedian();
147+
*/
148+
```
149+
150+
### **Go**
151+
152+
```go
153+
type MedianFinder struct {
154+
q1 hp
155+
q2 hp
156+
}
157+
158+
/** initialize your data structure here. */
159+
func Constructor() MedianFinder {
160+
return MedianFinder{hp{}, hp{}}
161+
}
162+
163+
func (this *MedianFinder) AddNum(num int) {
164+
heap.Push(&this.q1, num)
165+
heap.Push(&this.q2, -heap.Pop(&this.q1).(int))
166+
if this.q2.Len()-this.q1.Len() > 1 {
167+
heap.Push(&this.q1, -heap.Pop(&this.q2).(int))
168+
}
169+
}
170+
171+
func (this *MedianFinder) FindMedian() float64 {
172+
if this.q2.Len() > this.q1.Len() {
173+
return -float64(this.q2.IntSlice[0])
174+
}
175+
return float64(this.q1.IntSlice[0]-this.q2.IntSlice[0]) / 2.0
176+
}
177+
178+
/**
179+
* Your MedianFinder object will be instantiated and called as such:
180+
* obj := Constructor();
181+
* obj.AddNum(num);
182+
* param_2 := obj.FindMedian();
183+
*/
184+
185+
type hp struct{ sort.IntSlice }
186+
187+
func (h hp) Less(i, j int) bool { return h.IntSlice[i] < h.IntSlice[j] }
188+
func (h *hp) Push(v interface{}) { h.IntSlice = append(h.IntSlice, v.(int)) }
189+
func (h *hp) Pop() interface{} {
190+
a := h.IntSlice
191+
v := a[len(a)-1]
192+
h.IntSlice = a[:len(a)-1]
193+
return v
194+
}
195+
```
196+
110197
### **...**
111198

112199
```

0 commit comments

Comments
 (0)