dsa_visualizer 0.1.1 → 0.1.2
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/dsa_visualizer/algorithms/graph_algorithms.rb +322 -6
- data/lib/dsa_visualizer/algorithms/sorting.rb +106 -2
- data/lib/dsa_visualizer/data_structures/bst.rb +303 -2
- data/lib/dsa_visualizer/data_structures/deque.rb +208 -2
- data/lib/dsa_visualizer/data_structures/doubly_linked_list.rb +255 -2
- data/lib/dsa_visualizer/data_structures/graph.rb +191 -2
- data/lib/dsa_visualizer/data_structures/heap.rb +327 -4
- data/lib/dsa_visualizer/data_structures/priority_queue.rb +214 -2
- data/lib/dsa_visualizer/data_structures/trie.rb +261 -2
- data/lib/dsa_visualizer/data_structures/union_find.rb +207 -2
- metadata +5 -5
|
@@ -3,14 +3,337 @@ module DSAVisualizer
|
|
|
3
3
|
class Heap
|
|
4
4
|
def self.learn_min
|
|
5
5
|
Visualizer.print_header("MIN HEAP - Complete Binary Tree")
|
|
6
|
-
|
|
7
|
-
puts "
|
|
6
|
+
|
|
7
|
+
puts "\n📖 CONCEPT:"
|
|
8
|
+
puts "A Min Heap is a complete binary tree where:"
|
|
9
|
+
puts "• Parent is always smaller than its children"
|
|
10
|
+
puts "• Root contains the minimum element"
|
|
11
|
+
puts "• Implemented using array for efficiency"
|
|
12
|
+
puts "• Used in priority queues, heap sort, and graph algorithms"
|
|
13
|
+
|
|
14
|
+
puts "\n⏱️ TIME COMPLEXITY:"
|
|
15
|
+
puts "• Insert: O(log n)"
|
|
16
|
+
puts "• Extract Min: O(log n)"
|
|
17
|
+
puts "• Get Min: O(1)"
|
|
18
|
+
puts "• Build Heap: O(n)"
|
|
19
|
+
|
|
20
|
+
puts "\n💾 SPACE COMPLEXITY: O(n)"
|
|
21
|
+
|
|
22
|
+
demonstrate_min_heap
|
|
23
|
+
demonstrate_operations
|
|
24
|
+
show_array_representation
|
|
25
|
+
show_ruby_vs_cpp
|
|
26
|
+
show_practice_problems
|
|
8
27
|
end
|
|
9
28
|
|
|
10
29
|
def self.learn_max
|
|
11
30
|
Visualizer.print_header("MAX HEAP - Complete Binary Tree")
|
|
12
|
-
|
|
13
|
-
puts "
|
|
31
|
+
|
|
32
|
+
puts "\n📖 CONCEPT:"
|
|
33
|
+
puts "A Max Heap is a complete binary tree where:"
|
|
34
|
+
puts "• Parent is always larger than its children"
|
|
35
|
+
puts "• Root contains the maximum element"
|
|
36
|
+
puts "• Same structure as min heap, opposite ordering"
|
|
37
|
+
puts "• Used in heap sort and finding kth largest element"
|
|
38
|
+
|
|
39
|
+
puts "\n⏱️ TIME COMPLEXITY:"
|
|
40
|
+
puts "• Insert: O(log n)"
|
|
41
|
+
puts "• Extract Max: O(log n)"
|
|
42
|
+
puts "• Get Max: O(1)"
|
|
43
|
+
puts "• Build Heap: O(n)"
|
|
44
|
+
|
|
45
|
+
puts "\n💾 SPACE COMPLEXITY: O(n)"
|
|
46
|
+
|
|
47
|
+
demonstrate_max_heap
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def self.demonstrate_min_heap
|
|
51
|
+
puts "\n" + "="*60
|
|
52
|
+
puts "DEMONSTRATION: Min Heap Operations"
|
|
53
|
+
puts "="*60
|
|
54
|
+
|
|
55
|
+
heap = MinHeapImplementation.new
|
|
56
|
+
values = [10, 20, 5, 30, 15, 3]
|
|
57
|
+
|
|
58
|
+
puts "\nInserting: #{values.join(', ')}"
|
|
59
|
+
values.each do |val|
|
|
60
|
+
heap.insert(val)
|
|
61
|
+
puts "Inserted #{val}, Min: #{heap.peek}"
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
puts "\n📊 Heap Structure:"
|
|
65
|
+
puts " 3"
|
|
66
|
+
puts " / \\"
|
|
67
|
+
puts " 15 5"
|
|
68
|
+
puts " / \\ /"
|
|
69
|
+
puts " 30 20 10"
|
|
70
|
+
|
|
71
|
+
puts "\nArray representation: #{heap.to_a.inspect}"
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
def self.demonstrate_max_heap
|
|
75
|
+
puts "\n" + "="*60
|
|
76
|
+
puts "DEMONSTRATION: Max Heap Operations"
|
|
77
|
+
puts "="*60
|
|
78
|
+
|
|
79
|
+
heap = MaxHeapImplementation.new
|
|
80
|
+
values = [10, 20, 5, 30, 15, 3]
|
|
81
|
+
|
|
82
|
+
puts "\nInserting: #{values.join(', ')}"
|
|
83
|
+
values.each { |val| heap.insert(val) }
|
|
84
|
+
|
|
85
|
+
puts "\n📊 Heap Structure:"
|
|
86
|
+
puts " 30"
|
|
87
|
+
puts " / \\"
|
|
88
|
+
puts " 20 10"
|
|
89
|
+
puts " / \\ /"
|
|
90
|
+
puts " 15 5 3"
|
|
91
|
+
|
|
92
|
+
puts "\nExtracting max elements:"
|
|
93
|
+
3.times { puts "Extracted: #{heap.extract_max}" }
|
|
94
|
+
end
|
|
95
|
+
|
|
96
|
+
def self.demonstrate_operations
|
|
97
|
+
puts "\n" + "="*60
|
|
98
|
+
puts "MIN HEAP OPERATIONS"
|
|
99
|
+
puts "="*60
|
|
100
|
+
|
|
101
|
+
heap = MinHeapImplementation.new
|
|
102
|
+
[10, 20, 5, 30, 15].each { |v| heap.insert(v) }
|
|
103
|
+
|
|
104
|
+
puts "\n1️⃣ PEEK (Get Min):"
|
|
105
|
+
puts "Minimum: #{heap.peek}"
|
|
106
|
+
|
|
107
|
+
puts "\n2️⃣ EXTRACT MIN:"
|
|
108
|
+
puts "Extracted: #{heap.extract_min}"
|
|
109
|
+
puts "New minimum: #{heap.peek}"
|
|
110
|
+
|
|
111
|
+
puts "\n3️⃣ HEAP SORT:"
|
|
112
|
+
sorted = []
|
|
113
|
+
sorted << heap.extract_min until heap.empty?
|
|
114
|
+
puts "Sorted: #{sorted.join(', ')}"
|
|
115
|
+
end
|
|
116
|
+
|
|
117
|
+
def self.show_array_representation
|
|
118
|
+
puts "\n" + "="*60
|
|
119
|
+
puts "ARRAY REPRESENTATION"
|
|
120
|
+
puts "="*60
|
|
121
|
+
|
|
122
|
+
puts "\nFor node at index i:"
|
|
123
|
+
puts "• Left child: 2*i + 1"
|
|
124
|
+
puts "• Right child: 2*i + 2"
|
|
125
|
+
puts "• Parent: (i-1)/2"
|
|
126
|
+
|
|
127
|
+
puts "\nExample: [3, 15, 5, 30, 20, 10]"
|
|
128
|
+
puts "Index: 0 1 2 3 4 5"
|
|
129
|
+
puts ""
|
|
130
|
+
puts "Node 3 (index 0): children at 1 and 2 → 15, 5"
|
|
131
|
+
puts "Node 15 (index 1): children at 3 and 4 → 30, 20"
|
|
132
|
+
puts "Node 30 (index 3): parent at (3-1)/2 = 1 → 15"
|
|
133
|
+
end
|
|
134
|
+
|
|
135
|
+
def self.show_ruby_vs_cpp
|
|
136
|
+
puts "\n" + "="*60
|
|
137
|
+
puts "RUBY vs C++ IMPLEMENTATION"
|
|
138
|
+
puts "="*60
|
|
139
|
+
|
|
140
|
+
puts "\n🔴 RUBY:"
|
|
141
|
+
puts <<~RUBY
|
|
142
|
+
class MinHeap
|
|
143
|
+
def initialize
|
|
144
|
+
@heap = []
|
|
145
|
+
end
|
|
146
|
+
|
|
147
|
+
def insert(val)
|
|
148
|
+
@heap << val
|
|
149
|
+
heapify_up(@heap.size - 1)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def extract_min
|
|
153
|
+
return nil if @heap.empty?
|
|
154
|
+
min = @heap[0]
|
|
155
|
+
@heap[0] = @heap.pop
|
|
156
|
+
heapify_down(0) unless @heap.empty?
|
|
157
|
+
min
|
|
158
|
+
end
|
|
159
|
+
|
|
160
|
+
def heapify_up(index)
|
|
161
|
+
parent = (index - 1) / 2
|
|
162
|
+
if parent >= 0 && @heap[index] < @heap[parent]
|
|
163
|
+
@heap[index], @heap[parent] = @heap[parent], @heap[index]
|
|
164
|
+
heapify_up(parent)
|
|
165
|
+
end
|
|
166
|
+
end
|
|
167
|
+
end
|
|
168
|
+
RUBY
|
|
169
|
+
|
|
170
|
+
puts "\n🔵 C++:"
|
|
171
|
+
puts <<~CPP
|
|
172
|
+
#include <vector>
|
|
173
|
+
|
|
174
|
+
class MinHeap {
|
|
175
|
+
std::vector<int> heap;
|
|
176
|
+
public:
|
|
177
|
+
void insert(int val) {
|
|
178
|
+
heap.push_back(val);
|
|
179
|
+
heapifyUp(heap.size() - 1);
|
|
180
|
+
}
|
|
181
|
+
|
|
182
|
+
int extractMin() {
|
|
183
|
+
int min = heap[0];
|
|
184
|
+
heap[0] = heap.back();
|
|
185
|
+
heap.pop_back();
|
|
186
|
+
heapifyDown(0);
|
|
187
|
+
return min;
|
|
188
|
+
}
|
|
189
|
+
|
|
190
|
+
void heapifyUp(int index) {
|
|
191
|
+
int parent = (index - 1) / 2;
|
|
192
|
+
if (parent >= 0 && heap[index] < heap[parent]) {
|
|
193
|
+
swap(heap[index], heap[parent]);
|
|
194
|
+
heapifyUp(parent);
|
|
195
|
+
}
|
|
196
|
+
}
|
|
197
|
+
};
|
|
198
|
+
CPP
|
|
199
|
+
end
|
|
200
|
+
|
|
201
|
+
def self.show_practice_problems
|
|
202
|
+
puts "\n" + "="*60
|
|
203
|
+
puts "PRACTICE PROBLEMS"
|
|
204
|
+
puts "="*60
|
|
205
|
+
|
|
206
|
+
problems = [
|
|
207
|
+
"1. Kth largest element in array",
|
|
208
|
+
"2. Merge K sorted lists",
|
|
209
|
+
"3. Find median from data stream",
|
|
210
|
+
"4. Top K frequent elements",
|
|
211
|
+
"5. Sort nearly sorted array",
|
|
212
|
+
"6. Connect n ropes with minimum cost",
|
|
213
|
+
"7. K closest points to origin",
|
|
214
|
+
"8. Reorganize string (no adjacent duplicates)"
|
|
215
|
+
]
|
|
216
|
+
|
|
217
|
+
problems.each { |p| puts p }
|
|
218
|
+
|
|
219
|
+
puts "\n💡 TIP: Use max heap for kth smallest, min heap for kth largest!"
|
|
220
|
+
puts "💡 TIP: Building heap from array is O(n), not O(n log n)!"
|
|
221
|
+
end
|
|
222
|
+
|
|
223
|
+
class MinHeapImplementation
|
|
224
|
+
def initialize
|
|
225
|
+
@heap = []
|
|
226
|
+
end
|
|
227
|
+
|
|
228
|
+
def insert(val)
|
|
229
|
+
@heap << val
|
|
230
|
+
heapify_up(@heap.size - 1)
|
|
231
|
+
end
|
|
232
|
+
|
|
233
|
+
def extract_min
|
|
234
|
+
return nil if @heap.empty?
|
|
235
|
+
|
|
236
|
+
min = @heap[0]
|
|
237
|
+
@heap[0] = @heap.pop
|
|
238
|
+
heapify_down(0) unless @heap.empty?
|
|
239
|
+
min
|
|
240
|
+
end
|
|
241
|
+
|
|
242
|
+
def peek
|
|
243
|
+
@heap[0]
|
|
244
|
+
end
|
|
245
|
+
|
|
246
|
+
def empty?
|
|
247
|
+
@heap.empty?
|
|
248
|
+
end
|
|
249
|
+
|
|
250
|
+
def size
|
|
251
|
+
@heap.size
|
|
252
|
+
end
|
|
253
|
+
|
|
254
|
+
def to_a
|
|
255
|
+
@heap.dup
|
|
256
|
+
end
|
|
257
|
+
|
|
258
|
+
private
|
|
259
|
+
|
|
260
|
+
def heapify_up(index)
|
|
261
|
+
return if index == 0
|
|
262
|
+
|
|
263
|
+
parent = (index - 1) / 2
|
|
264
|
+
if @heap[index] < @heap[parent]
|
|
265
|
+
@heap[index], @heap[parent] = @heap[parent], @heap[index]
|
|
266
|
+
heapify_up(parent)
|
|
267
|
+
end
|
|
268
|
+
end
|
|
269
|
+
|
|
270
|
+
def heapify_down(index)
|
|
271
|
+
left = 2 * index + 1
|
|
272
|
+
right = 2 * index + 2
|
|
273
|
+
smallest = index
|
|
274
|
+
|
|
275
|
+
smallest = left if left < @heap.size && @heap[left] < @heap[smallest]
|
|
276
|
+
smallest = right if right < @heap.size && @heap[right] < @heap[smallest]
|
|
277
|
+
|
|
278
|
+
if smallest != index
|
|
279
|
+
@heap[index], @heap[smallest] = @heap[smallest], @heap[index]
|
|
280
|
+
heapify_down(smallest)
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
end
|
|
284
|
+
|
|
285
|
+
class MaxHeapImplementation
|
|
286
|
+
def initialize
|
|
287
|
+
@heap = []
|
|
288
|
+
end
|
|
289
|
+
|
|
290
|
+
def insert(val)
|
|
291
|
+
@heap << val
|
|
292
|
+
heapify_up(@heap.size - 1)
|
|
293
|
+
end
|
|
294
|
+
|
|
295
|
+
def extract_max
|
|
296
|
+
return nil if @heap.empty?
|
|
297
|
+
|
|
298
|
+
max = @heap[0]
|
|
299
|
+
@heap[0] = @heap.pop
|
|
300
|
+
heapify_down(0) unless @heap.empty?
|
|
301
|
+
max
|
|
302
|
+
end
|
|
303
|
+
|
|
304
|
+
def peek
|
|
305
|
+
@heap[0]
|
|
306
|
+
end
|
|
307
|
+
|
|
308
|
+
def empty?
|
|
309
|
+
@heap.empty?
|
|
310
|
+
end
|
|
311
|
+
|
|
312
|
+
private
|
|
313
|
+
|
|
314
|
+
def heapify_up(index)
|
|
315
|
+
return if index == 0
|
|
316
|
+
|
|
317
|
+
parent = (index - 1) / 2
|
|
318
|
+
if @heap[index] > @heap[parent]
|
|
319
|
+
@heap[index], @heap[parent] = @heap[parent], @heap[index]
|
|
320
|
+
heapify_up(parent)
|
|
321
|
+
end
|
|
322
|
+
end
|
|
323
|
+
|
|
324
|
+
def heapify_down(index)
|
|
325
|
+
left = 2 * index + 1
|
|
326
|
+
right = 2 * index + 2
|
|
327
|
+
largest = index
|
|
328
|
+
|
|
329
|
+
largest = left if left < @heap.size && @heap[left] > @heap[largest]
|
|
330
|
+
largest = right if right < @heap.size && @heap[right] > @heap[largest]
|
|
331
|
+
|
|
332
|
+
if largest != index
|
|
333
|
+
@heap[index], @heap[largest] = @heap[largest], @heap[index]
|
|
334
|
+
heapify_down(largest)
|
|
335
|
+
end
|
|
336
|
+
end
|
|
14
337
|
end
|
|
15
338
|
end
|
|
16
339
|
end
|
|
@@ -3,8 +3,220 @@ module DSAVisualizer
|
|
|
3
3
|
class PriorityQueue
|
|
4
4
|
def self.learn
|
|
5
5
|
Visualizer.print_header("PRIORITY QUEUE - Heap-Based Queue")
|
|
6
|
-
|
|
7
|
-
puts "
|
|
6
|
+
|
|
7
|
+
puts "\n📖 CONCEPT:"
|
|
8
|
+
puts "A Priority Queue is an abstract data type where:"
|
|
9
|
+
puts "• Each element has a priority"
|
|
10
|
+
puts "• Higher priority elements are dequeued first"
|
|
11
|
+
puts "• Typically implemented using heaps"
|
|
12
|
+
puts "• Used in scheduling, graph algorithms (Dijkstra, Prim)"
|
|
13
|
+
|
|
14
|
+
puts "\n⏱️ TIME COMPLEXITY:"
|
|
15
|
+
puts "• Insert: O(log n)"
|
|
16
|
+
puts "• Extract Max/Min: O(log n)"
|
|
17
|
+
puts "• Peek: O(1)"
|
|
18
|
+
puts "• Build: O(n)"
|
|
19
|
+
|
|
20
|
+
puts "\n💾 SPACE COMPLEXITY: O(n)"
|
|
21
|
+
|
|
22
|
+
demonstrate_priority_queue
|
|
23
|
+
demonstrate_applications
|
|
24
|
+
show_ruby_vs_cpp
|
|
25
|
+
show_practice_problems
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def self.demonstrate_priority_queue
|
|
29
|
+
puts "\n" + "="*60
|
|
30
|
+
puts "DEMONSTRATION: Priority Queue Operations"
|
|
31
|
+
puts "="*60
|
|
32
|
+
|
|
33
|
+
pq = PriorityQueueImplementation.new
|
|
34
|
+
|
|
35
|
+
puts "\nInserting tasks with priorities:"
|
|
36
|
+
tasks = [
|
|
37
|
+
{ task: "Email", priority: 2 },
|
|
38
|
+
{ task: "Meeting", priority: 5 },
|
|
39
|
+
{ task: "Coffee", priority: 1 },
|
|
40
|
+
{ task: "Deadline", priority: 10 },
|
|
41
|
+
{ task: "Lunch", priority: 3 }
|
|
42
|
+
]
|
|
43
|
+
|
|
44
|
+
tasks.each do |t|
|
|
45
|
+
pq.insert(t[:task], t[:priority])
|
|
46
|
+
puts "Added: #{t[:task]} (priority: #{t[:priority]})"
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
puts "\n📊 Processing by priority (highest first):"
|
|
50
|
+
until pq.empty?
|
|
51
|
+
task, priority = pq.extract_max
|
|
52
|
+
puts "Processing: #{task} (priority: #{priority})"
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
|
|
56
|
+
def self.demonstrate_applications
|
|
57
|
+
puts "\n" + "="*60
|
|
58
|
+
puts "REAL-WORLD APPLICATIONS"
|
|
59
|
+
puts "="*60
|
|
60
|
+
|
|
61
|
+
puts "\n1️⃣ CPU SCHEDULING:"
|
|
62
|
+
puts "Process with highest priority gets CPU time first"
|
|
63
|
+
|
|
64
|
+
puts "\n2️⃣ DIJKSTRA'S ALGORITHM:"
|
|
65
|
+
puts "Always process vertex with minimum distance"
|
|
66
|
+
|
|
67
|
+
puts "\n3️⃣ HUFFMAN CODING:"
|
|
68
|
+
puts "Build tree by merging nodes with lowest frequency"
|
|
69
|
+
|
|
70
|
+
puts "\n4️⃣ EVENT-DRIVEN SIMULATION:"
|
|
71
|
+
puts "Process events in chronological order"
|
|
72
|
+
|
|
73
|
+
puts "\n5️⃣ LOAD BALANCING:"
|
|
74
|
+
puts "Assign tasks to least loaded server"
|
|
75
|
+
|
|
76
|
+
puts "\n6️⃣ A* PATHFINDING:"
|
|
77
|
+
puts "Explore nodes with best estimated cost first"
|
|
78
|
+
end
|
|
79
|
+
|
|
80
|
+
def self.show_ruby_vs_cpp
|
|
81
|
+
puts "\n" + "="*60
|
|
82
|
+
puts "RUBY vs C++ IMPLEMENTATION"
|
|
83
|
+
puts "="*60
|
|
84
|
+
|
|
85
|
+
puts "\n🔴 RUBY:"
|
|
86
|
+
puts <<~RUBY
|
|
87
|
+
class PriorityQueue
|
|
88
|
+
def initialize
|
|
89
|
+
@heap = []
|
|
90
|
+
end
|
|
91
|
+
|
|
92
|
+
def insert(item, priority)
|
|
93
|
+
@heap << [item, priority]
|
|
94
|
+
heapify_up(@heap.size - 1)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def extract_max
|
|
98
|
+
return nil if @heap.empty?
|
|
99
|
+
max = @heap[0]
|
|
100
|
+
@heap[0] = @heap.pop
|
|
101
|
+
heapify_down(0) unless @heap.empty?
|
|
102
|
+
max
|
|
103
|
+
end
|
|
104
|
+
|
|
105
|
+
def heapify_up(index)
|
|
106
|
+
parent = (index - 1) / 2
|
|
107
|
+
if parent >= 0 && @heap[index][1] > @heap[parent][1]
|
|
108
|
+
@heap[index], @heap[parent] = @heap[parent], @heap[index]
|
|
109
|
+
heapify_up(parent)
|
|
110
|
+
end
|
|
111
|
+
end
|
|
112
|
+
end
|
|
113
|
+
RUBY
|
|
114
|
+
|
|
115
|
+
puts "\n🔵 C++:"
|
|
116
|
+
puts <<~CPP
|
|
117
|
+
#include <queue>
|
|
118
|
+
#include <vector>
|
|
119
|
+
|
|
120
|
+
// Using STL priority_queue (max heap by default)
|
|
121
|
+
std::priority_queue<int> pq;
|
|
122
|
+
pq.push(10);
|
|
123
|
+
pq.push(30);
|
|
124
|
+
pq.push(20);
|
|
125
|
+
int max = pq.top(); // 30
|
|
126
|
+
pq.pop();
|
|
127
|
+
|
|
128
|
+
// Min heap version
|
|
129
|
+
std::priority_queue<int, std::vector<int>, std::greater<int>> minPQ;
|
|
130
|
+
|
|
131
|
+
// Custom comparator
|
|
132
|
+
struct Task {
|
|
133
|
+
string name;
|
|
134
|
+
int priority;
|
|
135
|
+
};
|
|
136
|
+
|
|
137
|
+
auto cmp = [](Task a, Task b) { return a.priority < b.priority; };
|
|
138
|
+
std::priority_queue<Task, std::vector<Task>, decltype(cmp)> taskPQ(cmp);
|
|
139
|
+
CPP
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def self.show_practice_problems
|
|
143
|
+
puts "\n" + "="*60
|
|
144
|
+
puts "PRACTICE PROBLEMS"
|
|
145
|
+
puts "="*60
|
|
146
|
+
|
|
147
|
+
problems = [
|
|
148
|
+
"1. Kth largest element in stream",
|
|
149
|
+
"2. Merge K sorted arrays",
|
|
150
|
+
"3. Find median in data stream",
|
|
151
|
+
"4. Task scheduler with cooldown",
|
|
152
|
+
"5. Meeting rooms II (min rooms needed)",
|
|
153
|
+
"6. Top K frequent words",
|
|
154
|
+
"7. Reorganize string",
|
|
155
|
+
"8. Minimum cost to connect sticks"
|
|
156
|
+
]
|
|
157
|
+
|
|
158
|
+
problems.each { |p| puts p }
|
|
159
|
+
|
|
160
|
+
puts "\n💡 TIP: Use min heap when you need smallest, max heap for largest!"
|
|
161
|
+
puts "💡 TIP: Priority queue is perfect for 'Kth largest/smallest' problems"
|
|
162
|
+
end
|
|
163
|
+
|
|
164
|
+
class PriorityQueueImplementation
|
|
165
|
+
def initialize
|
|
166
|
+
@heap = [] # Array of [item, priority] pairs
|
|
167
|
+
end
|
|
168
|
+
|
|
169
|
+
def insert(item, priority)
|
|
170
|
+
@heap << [item, priority]
|
|
171
|
+
heapify_up(@heap.size - 1)
|
|
172
|
+
end
|
|
173
|
+
|
|
174
|
+
def extract_max
|
|
175
|
+
return nil if @heap.empty?
|
|
176
|
+
|
|
177
|
+
max = @heap[0]
|
|
178
|
+
@heap[0] = @heap.pop
|
|
179
|
+
heapify_down(0) unless @heap.empty?
|
|
180
|
+
max
|
|
181
|
+
end
|
|
182
|
+
|
|
183
|
+
def peek
|
|
184
|
+
@heap[0]
|
|
185
|
+
end
|
|
186
|
+
|
|
187
|
+
def empty?
|
|
188
|
+
@heap.empty?
|
|
189
|
+
end
|
|
190
|
+
|
|
191
|
+
def size
|
|
192
|
+
@heap.size
|
|
193
|
+
end
|
|
194
|
+
|
|
195
|
+
private
|
|
196
|
+
|
|
197
|
+
def heapify_up(index)
|
|
198
|
+
return if index == 0
|
|
199
|
+
|
|
200
|
+
parent = (index - 1) / 2
|
|
201
|
+
if @heap[index][1] > @heap[parent][1]
|
|
202
|
+
@heap[index], @heap[parent] = @heap[parent], @heap[index]
|
|
203
|
+
heapify_up(parent)
|
|
204
|
+
end
|
|
205
|
+
end
|
|
206
|
+
|
|
207
|
+
def heapify_down(index)
|
|
208
|
+
left = 2 * index + 1
|
|
209
|
+
right = 2 * index + 2
|
|
210
|
+
largest = index
|
|
211
|
+
|
|
212
|
+
largest = left if left < @heap.size && @heap[left][1] > @heap[largest][1]
|
|
213
|
+
largest = right if right < @heap.size && @heap[right][1] > @heap[largest][1]
|
|
214
|
+
|
|
215
|
+
if largest != index
|
|
216
|
+
@heap[index], @heap[largest] = @heap[largest], @heap[index]
|
|
217
|
+
heapify_down(largest)
|
|
218
|
+
end
|
|
219
|
+
end
|
|
8
220
|
end
|
|
9
221
|
end
|
|
10
222
|
end
|