Skip to content

Commit 7ad79d6

Browse files
authored
Improved task 295
1 parent 22d2eb7 commit 7ad79d6

File tree

3 files changed

+84
-207
lines changed

3 files changed

+84
-207
lines changed

README.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1427,7 +1427,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated.
14271427
| 0338 |[Counting Bits](src/main/ts/g0301_0400/s0338_counting_bits/solution.ts)| Easy | Top_100_Liked_Questions, Dynamic_Programming, Bit_Manipulation, Udemy_Bit_Manipulation, Big_O_Time_O(num)_Space_O(num) | 69 | 86.81
14281428
| 0322 |[Coin Change](src/main/ts/g0301_0400/s0322_coin_change/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Breadth_First_Search, Algorithm_II_Day_18_Dynamic_Programming, Dynamic_Programming_I_Day_20, Level_2_Day_12_Dynamic_Programming, Big_O_Time_O(m*n)_Space_O(amount) | 85 | 86.14
14291429
| 0300 |[Longest Increasing Subsequence](src/main/ts/g0201_0300/s0300_longest_increasing_subsequence/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Dynamic_Programming, Binary_Search, Algorithm_II_Day_16_Dynamic_Programming, Binary_Search_II_Day_3, Dynamic_Programming_I_Day_18, Udemy_Dynamic_Programming, Big_O_Time_O(n*log_n)_Space_O(n) | 57 | 93.75
1430-
| 0295 |[Find Median from Data Stream](src/main/ts/g0201_0300/s0295_find_median_from_data_stream/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Sorting, Two_Pointers, Design, Heap_Priority_Queue, Data_Stream, Big_O_Time_O(n*log_n)_Space_O(n) | 426 | 85.33
1430+
| 0295 |[Find Median from Data Stream](src/main/ts/g0201_0300/s0295_find_median_from_data_stream/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Sorting, Two_Pointers, Design, Heap_Priority_Queue, Data_Stream, Big_O_Time_O(n*log_n)_Space_O(n) | 335 | 99.44
14311431
| 0287 |[Find the Duplicate Number](src/main/ts/g0201_0300/s0287_find_the_duplicate_number/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Two_Pointers, Bit_Manipulation, Binary_Search_II_Day_5, Big_O_Time_O(n)_Space_O(n) | 60 | 98.11
14321432
| 0283 |[Move Zeroes](src/main/ts/g0201_0300/s0283_move_zeroes/solution.ts)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Array, Two_Pointers, Algorithm_I_Day_3_Two_Pointers, Programming_Skills_I_Day_6_Array, Udemy_Arrays, Big_O_Time_O(n)_Space_O(1) | 71 | 91.63
14331433
| 0240 |[Search a 2D Matrix II](src/main/ts/g0201_0300/s0240_search_a_2d_matrix_ii/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, Array, Binary_Search, Matrix, Divide_and_Conquer, Data_Structure_II_Day_4_Array, Binary_Search_II_Day_8, Big_O_Time_O(n+m)_Space_O(1) | 58 | 64.44
@@ -1498,7 +1498,7 @@ TypeScript-based LeetCode algorithm problem solutions, regularly updated.
14981498
| 0031 |[Next Permutation](src/main/ts/g0001_0100/s0031_next_permutation/solution.ts)| Medium | Top_100_Liked_Questions, Array, Two_Pointers, Big_O_Time_O(n)_Space_O(1) | 47 | 99.30
14991499
| 0025 |[Reverse Nodes in k-Group](src/main/ts/g0001_0100/s0025_reverse_nodes_in_k_group/solution.ts)| Hard | Top_100_Liked_Questions, Linked_List, Recursion, Data_Structure_II_Day_13_Linked_List, Udemy_Linked_List, Big_O_Time_O(n)_Space_O(k) | 74 | 66.83
15001500
| 0024 |[Swap Nodes in Pairs](src/main/ts/g0001_0100/s0024_swap_nodes_in_pairs/solution.ts)| Medium | Top_100_Liked_Questions, Linked_List, Recursion, Data_Structure_II_Day_12_Linked_List, Udemy_Linked_List, Big_O_Time_O(n)_Space_O(1) | 59 | 62.67
1501-
| 0023 |[Merge k Sorted Lists](src/main/ts/g0001_0100/s0023_merge_k_sorted_lists/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Heap_Priority_Queue, Linked_List, Divide_and_Conquer, Merge_Sort, Big_O_Time_O(k*n*log(k))_Space_O(log(k)) | 75 | 97.06
1501+
| 0023 |[Merge k Sorted Lists](src/main/ts/g0001_0100/s0023_merge_k_sorted_lists/solution.ts)| Hard | Top_100_Liked_Questions, Top_Interview_Questions, Heap_Priority_Queue, Linked_List, Divide_and_Conquer, Merge_Sort, Big_O_Time_O(k*n*log(k))_Space_O(log(k)) | 76 | 94.52
15021502
| 0022 |[Generate Parentheses](src/main/ts/g0001_0100/s0022_generate_parentheses/solution.ts)| Medium | Top_100_Liked_Questions, Top_Interview_Questions, String, Dynamic_Programming, Backtracking, Algorithm_II_Day_11_Recursion_Backtracking, Udemy_Backtracking/Recursion, Big_O_Time_O(2^n)_Space_O(n) | 60 | 62.03
15031503
| 0021 |[Merge Two Sorted Lists](src/main/ts/g0001_0100/s0021_merge_two_sorted_lists/solution.ts)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, Linked_List, Recursion, Data_Structure_I_Day_7_Linked_List, Algorithm_I_Day_10_Recursion_Backtracking, Level_1_Day_3_Linked_List, Udemy_Linked_List, Big_O_Time_O(m+n)_Space_O(m+n) | 59 | 86.77
15041504
| 0020 |[Valid Parentheses](src/main/ts/g0001_0100/s0020_valid_parentheses/solution.ts)| Easy | Top_100_Liked_Questions, Top_Interview_Questions, String, Stack, Data_Structure_I_Day_9_Stack_Queue, Udemy_Strings, Big_O_Time_O(n)_Space_O(n) | 50 | 95.90

src/main/ts/g0201_0300/s0295_find_median_from_data_stream/solution.ts

Lines changed: 57 additions & 205 deletions
Original file line numberDiff line numberDiff line change
@@ -1,242 +1,94 @@
11
// #Hard #Top_100_Liked_Questions #Top_Interview_Questions #Sorting #Two_Pointers #Design
22
// #Heap_Priority_Queue #Data_Stream #Big_O_Time_O(n*log_n)_Space_O(n)
3-
// #2023_10_06_Time_426_ms_(85.33%)_Space_98.1_MB_(48.67%)
3+
// #2023_10_13_Time_335_ms_(99.44%)_Space_96.8_MB_(69.49%)
44

5-
class MaxHeap<T> {
6-
private heap: T[]
5+
class Heap {
6+
private heap: number[]
77

88
constructor() {
9-
this.heap = []
9+
this.heap = [0]
1010
}
1111

12-
size(): number {
13-
return this.heap.length
12+
peek(): number | null {
13+
return this.heap[1] ?? null
1414
}
1515

16-
isEmpty(): boolean {
17-
return this.heap.length === 0
18-
}
19-
20-
peek(): T {
21-
return this.heap[0]
22-
}
23-
24-
add(value: T): void {
25-
this.heap.push(value)
26-
this.heapifyUp()
27-
}
28-
29-
poll(): T {
30-
const max = this.heap[0]
31-
const last = this.heap.pop()
32-
if (this.heap.length > 0) {
33-
this.heap[0] = last
34-
this.heapifyDown()
35-
}
36-
return max
37-
}
38-
39-
private heapifyUp(): void {
40-
let currentIndex = this.heap.length - 1
41-
while (this.hasParent(currentIndex) && this.parent(currentIndex) < this.heap[currentIndex]) {
42-
const parentIndex = this.getParentIndex(currentIndex)
43-
this.swap(parentIndex, currentIndex)
44-
currentIndex = parentIndex
45-
}
46-
}
47-
48-
private heapifyDown(): void {
49-
let currentIndex = 0
50-
while (this.hasLeftChild(currentIndex)) {
51-
let biggerChildIndex = this.getLeftChildIndex(currentIndex)
52-
if (this.hasRightChild(currentIndex) && this.rightChild(currentIndex) > this.leftChild(currentIndex)) {
53-
biggerChildIndex = this.getRightChildIndex(currentIndex)
54-
}
55-
56-
if (this.heap[currentIndex] > this.heap[biggerChildIndex]) {
57-
break
58-
}
59-
60-
this.swap(currentIndex, biggerChildIndex)
61-
currentIndex = biggerChildIndex
16+
push(val: number): void {
17+
this.heap.push(val)
18+
let i = this.heap.length - 1
19+
let parI = Math.floor(i / 2)
20+
while (i > 1 && this.heap[i] < this.heap[parI]) {
21+
const tmp = this.heap[i]
22+
this.heap[i] = this.heap[parI]
23+
this.heap[parI] = tmp
24+
i = parI
25+
parI = Math.floor(i / 2)
6226
}
6327
}
6428

65-
private hasParent(index: number): boolean {
66-
return this.getParentIndex(index) >= 0
67-
}
68-
69-
private hasLeftChild(index: number): boolean {
70-
return this.getLeftChildIndex(index) < this.heap.length
71-
}
72-
73-
private hasRightChild(index: number): boolean {
74-
return this.getRightChildIndex(index) < this.heap.length
75-
}
76-
77-
private parent(index: number): T {
78-
return this.heap[this.getParentIndex(index)]
79-
}
80-
81-
private leftChild(index: number): T {
82-
return this.heap[this.getLeftChildIndex(index)]
83-
}
84-
85-
private rightChild(index: number): T {
86-
return this.heap[this.getRightChildIndex(index)]
87-
}
88-
89-
private getParentIndex(index: number): number {
90-
return Math.floor((index - 1) / 2)
91-
}
92-
93-
private getLeftChildIndex(index: number): number {
94-
return index * 2 + 1
95-
}
96-
97-
private getRightChildIndex(index: number): number {
98-
return index * 2 + 2
99-
}
100-
101-
private swap(index1: number, index2: number): void {
102-
const temp = this.heap[index1]
103-
this.heap[index1] = this.heap[index2]
104-
this.heap[index2] = temp
105-
}
106-
}
107-
108-
class MinHeap<T> {
109-
private heap: T[]
110-
111-
constructor() {
112-
this.heap = []
113-
}
114-
115-
size(): number {
116-
return this.heap.length
117-
}
118-
119-
isEmpty(): boolean {
120-
return this.heap.length === 0
121-
}
122-
123-
peek(): T {
124-
return this.heap[0]
125-
}
126-
127-
add(value: T): void {
128-
this.heap.push(value)
129-
this.heapifyUp()
130-
}
131-
132-
poll(): T {
133-
const min = this.heap[0]
134-
const last = this.heap.pop()
135-
if (this.heap.length > 0) {
136-
this.heap[0] = last
137-
this.heapifyDown()
29+
pop(): number | null {
30+
if (this.heap.length == 1) {
31+
return null
13832
}
139-
return min
140-
}
141-
142-
private heapifyUp(): void {
143-
let currentIndex = this.heap.length - 1
144-
while (this.hasParent(currentIndex) && this.parent(currentIndex) > this.heap[currentIndex]) {
145-
const parentIndex = this.getParentIndex(currentIndex)
146-
this.swap(parentIndex, currentIndex)
147-
currentIndex = parentIndex
33+
if (this.heap.length == 2) {
34+
return this.heap.pop()
14835
}
149-
}
150-
151-
private heapifyDown(): void {
152-
let currentIndex = 0
153-
while (this.hasLeftChild(currentIndex)) {
154-
let smallerChildIndex = this.getLeftChildIndex(currentIndex)
155-
if (this.hasRightChild(currentIndex) && this.rightChild(currentIndex) < this.leftChild(currentIndex)) {
156-
smallerChildIndex = this.getRightChildIndex(currentIndex)
157-
}
158-
159-
if (this.heap[currentIndex] < this.heap[smallerChildIndex]) {
36+
const res = this.heap[1]
37+
this.heap[1] = this.heap.pop()
38+
let i = 1
39+
while (2 * i < this.heap.length) {
40+
const leftChildIdx = 2 * i
41+
const rightChildIdx = 2 * i + 1
42+
if (
43+
rightChildIdx < this.heap.length &&
44+
this.heap[rightChildIdx] < this.heap[leftChildIdx] &&
45+
this.heap[i] > this.heap[rightChildIdx]
46+
) {
47+
const tmp = this.heap[i]
48+
this.heap[i] = this.heap[rightChildIdx]
49+
this.heap[rightChildIdx] = tmp
50+
i = rightChildIdx
51+
} else if (this.heap[i] > this.heap[leftChildIdx]) {
52+
const tmp = this.heap[i]
53+
this.heap[i] = this.heap[leftChildIdx]
54+
this.heap[leftChildIdx] = tmp
55+
i = leftChildIdx
56+
} else {
16057
break
16158
}
162-
163-
this.swap(currentIndex, smallerChildIndex)
164-
currentIndex = smallerChildIndex
16559
}
60+
return res
16661
}
16762

168-
private hasParent(index: number): boolean {
169-
return this.getParentIndex(index) >= 0
170-
}
171-
172-
private hasLeftChild(index: number): boolean {
173-
return this.getLeftChildIndex(index) < this.heap.length
174-
}
175-
176-
private hasRightChild(index: number): boolean {
177-
return this.getRightChildIndex(index) < this.heap.length
178-
}
179-
180-
private parent(index: number): T {
181-
return this.heap[this.getParentIndex(index)]
182-
}
183-
184-
private leftChild(index: number): T {
185-
return this.heap[this.getLeftChildIndex(index)]
186-
}
187-
188-
private rightChild(index: number): T {
189-
return this.heap[this.getRightChildIndex(index)]
190-
}
191-
192-
private getParentIndex(index: number): number {
193-
return Math.floor((index - 1) / 2)
194-
}
195-
196-
private getLeftChildIndex(index: number): number {
197-
return index * 2 + 1
198-
}
199-
200-
private getRightChildIndex(index: number): number {
201-
return index * 2 + 2
202-
}
203-
204-
private swap(index1: number, index2: number): void { //NOSONAR
205-
const temp = this.heap[index1]
206-
this.heap[index1] = this.heap[index2]
207-
this.heap[index2] = temp
63+
length(): number {
64+
return this.heap.length - 1
20865
}
20966
}
21067

21168
class MedianFinder {
212-
private maxHeap: MaxHeap<number>
213-
private minHeap: MinHeap<number>
69+
large: Heap
70+
small: Heap
21471

21572
constructor() {
216-
this.maxHeap = new MaxHeap<number>()
217-
this.minHeap = new MinHeap<number>()
73+
this.large = new Heap()
74+
this.small = new Heap()
21875
}
21976

22077
addNum(num: number): void {
221-
if (this.maxHeap.isEmpty() || num <= this.maxHeap.peek()) {
222-
this.maxHeap.add(num)
78+
if (this.small.length() === this.large.length()) {
79+
this.small.push(-num)
80+
this.large.push(-this.small.pop())
22381
} else {
224-
this.minHeap.add(num)
225-
}
226-
227-
if (this.maxHeap.size() - this.minHeap.size() > 1) {
228-
this.minHeap.add(this.maxHeap.poll())
229-
} else if (this.minHeap.size() > this.maxHeap.size()) {
230-
this.maxHeap.add(this.minHeap.poll())
82+
this.large.push(num)
83+
this.small.push(-this.large.pop())
23184
}
23285
}
23386

23487
findMedian(): number {
235-
if (this.maxHeap.size() === this.minHeap.size()) {
236-
return (this.maxHeap.peek() + this.minHeap.peek()) / 2
237-
} else {
238-
return this.maxHeap.size() > this.minHeap.size() ? this.maxHeap.peek() : this.minHeap.peek()
88+
if (this.small.length() === this.large.length()) {
89+
return (this.large.peek() - this.small.peek()) / 2
23990
}
91+
return this.large.peek()
24092
}
24193
}
24294

src/test/ts/g0201_0300/s0295_find_median_from_data_stream/solution.test.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,3 +18,28 @@ test('medianFinder2', () => {
1818
medianFinder.addNum(-1)
1919
expect(medianFinder.findMedian()).toEqual(1.0)
2020
})
21+
22+
test('medianFinder3', () => {
23+
const medianFinder = new MedianFinder()
24+
medianFinder.addNum(-1)
25+
medianFinder.addNum(-2)
26+
medianFinder.addNum(-3)
27+
medianFinder.addNum(-4)
28+
medianFinder.addNum(-5)
29+
expect(medianFinder.findMedian()).toEqual(-3.0)
30+
})
31+
32+
test('medianFinder4', () => {
33+
const medianFinder = new MedianFinder()
34+
medianFinder.addNum(1)
35+
medianFinder.addNum(2)
36+
medianFinder.addNum(3)
37+
medianFinder.addNum(4)
38+
medianFinder.addNum(5)
39+
medianFinder.addNum(6)
40+
medianFinder.addNum(7)
41+
medianFinder.addNum(8)
42+
medianFinder.addNum(9)
43+
medianFinder.addNum(10)
44+
expect(medianFinder.findMedian()).toEqual(5.5)
45+
})

0 commit comments

Comments
 (0)