Skip to content

Commit ad9bf5e

Browse files
Meto TrajkovskiMeto Trajkovski
authored andcommitted
Added and updated solutions with priority queue
1 parent 0fdb464 commit ad9bf5e

5 files changed

Lines changed: 69 additions & 31 deletions

File tree

Linked Lists/merge_k_sorted_ll.py

Lines changed: 7 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -35,34 +35,33 @@ def __lt__(self, other):
3535
return self.val < other.val
3636

3737
# priority queue
38-
class MyHeap:
38+
class PriorityQueue:
3939
def __init__(self):
4040
self.data = []
4141

4242
def push(self, node):
43-
heapq.heappush(self.data, node)
43+
heapq.heappush(self.data, PQNode(node))
4444

4545
def pop(self):
46-
return heapq.heappop(self.data)
46+
return heapq.heappop(self.data).node
4747

4848
def is_empty(self):
4949
return len(self.data) == 0
5050

5151
def merge_k_lists_1(lists):
52-
heap = MyHeap()
52+
heap = PriorityQueue()
5353

5454
# add all linked lists in the heap
5555
for node in lists:
5656
if node is not None:
57-
heap.push(PQNode(node))
57+
heap.push(node)
5858

5959
result = ListNode(-1)
6060
pointer = result
6161

6262
while not heap.is_empty():
6363
# in each step remove the min list from the heap
64-
el = heap.pop()
65-
node = el.node
64+
node = heap.pop()
6665

6766
# add the min list to the result
6867
pointer.next = node
@@ -71,7 +70,7 @@ def merge_k_lists_1(lists):
7170
node = node.next
7271
if node is not None:
7372
# take the next node from the min list and add it in the heap
74-
heap.push(PQNode(node))
73+
heap.push(node)
7574

7675
return result.next
7776

Lists/k_closest_points.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ def kth_closest(arr, k, left, right, pt):
4242
kth_closest(arr, k, pivot + 1, right, pt)
4343

4444
def pivoting(arr, left, right, pt):
45-
# O(N) pivoting
45+
# Linear time complexity pivoting
4646
# takes the last element as pivot
4747
pivot_dist = sqr_dist(pt, arr[right])
4848
new_pivot = left

Lists/kth_smallest.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -46,7 +46,7 @@ def kth_smallest(arr, k, left, right):
4646
return arr[pivot]
4747

4848
def pivoting(arr, left, right):
49-
# O(N) pivoting
49+
# Linear time complexity pivoting
5050
# takes the last element as pivot
5151
pivot = right
5252
new_pivot = left

Lists/running_median.py

Lines changed: 11 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -16,7 +16,7 @@
1616
2
1717
1818
=========================================
19-
Using 2 heaps (priority queues) balance the left and right side of the stream.
19+
Using 2 heaps (max and min Priority Queues) balance the left and right side of the stream.
2020
Time Complexity: O(N LogN)
2121
Space Complexity: O(N)
2222
'''
@@ -26,36 +26,36 @@
2626
# Solution #
2727
############
2828

29-
from heapq import heappush, heappop
29+
import heapq
3030

3131
class PriorityQueue:
32-
def __init__(self, isMin=True):
32+
def __init__(self, is_min=True):
3333
self.data = []
34-
self.isMin = isMin
34+
self.is_min = is_min
3535

3636
def push(self, el):
37-
if not self.isMin:
37+
if not self.is_min:
3838
el = -el
39-
heappush(self.data, el)
39+
heapq.heappush(self.data, el)
4040

4141
def pop(self):
42-
el = heappop(self.data)
43-
if not self.isMin:
42+
el = heapq.heappop(self.data)
43+
if not self.is_min:
4444
el = -el
4545
return el
4646

4747
def peek(self):
4848
el = self.data[0]
49-
if not self.isMin:
49+
if not self.is_min:
5050
el = -el
5151
return el
5252

5353
def count(self):
5454
return len(self.data)
5555

5656
def running_median(stream):
57-
left_heap = PriorityQueue(False)
58-
right_heap = PriorityQueue()
57+
left_heap = PriorityQueue(False) # Max Priority Queue
58+
right_heap = PriorityQueue() # Min Priority Queue
5959

6060
# left_heap will have always same number of elements or 1 element more than right_heap
6161
for number in stream:

Lists/top_k_frequent_elements.py

Lines changed: 49 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,7 @@
22
Top K Frequent Elements
33
44
Given a non-empty array of integers, return the k most frequent elements.
5+
The order of the result isn't important.
56
67
Input: [1, 1, 1, 2, 2, 3], 2
78
Output: [1, 2]
@@ -10,12 +11,13 @@
1011
Output: [1]
1112
1213
=========================================
13-
Using Priority Queue, add each frequency and remove the last if there are more than K elements inside the Priority Queue.
14-
Time Complexity: O(N LogK)
14+
Using Min Priority Queue, in each step add an element with its frequency and remove the element with the smallest frequency
15+
if there are more than K elements inside the Priority Queue. This solution isn't much faster than sorting the frequencies.
16+
Time Complexity: O(U LogK) , U in this case is the number of unique elements (but all elements from the array could be unique, so because of that U can be equal to N)
1517
Space Complexity: O(N)
1618
Using pivoting, this solution is based on the quick sort algorithm (divide and conquer).
17-
Same pivoting solution as the nth_smallest.py,
18-
Time Complexity: O(N)
19+
Same pivoting solution as the nth_smallest.py.
20+
Time Complexity: O(U)
1921
Space Complexity: O(N)
2022
'''
2123

@@ -24,10 +26,37 @@
2426
# Solution 1 #
2527
##############
2628

29+
import heapq
30+
31+
# priority queue comparator class
32+
# acctualy in this case you don't need a comparator class, because the elements are tuples
33+
# and comparison operator can work with tuples
34+
# (The comparison starts with a first element of each tuple. If they do not compare to =,< or > then it proceed to the second element and so on.)
35+
class PQElement:
36+
def __init__(self, el):
37+
self.frequency, self.val = el
38+
39+
def __lt__(self, other):
40+
return self.frequency < other.frequency
41+
42+
# priority queue
43+
class PriorityQueue:
44+
def __init__(self):
45+
self.data = []
46+
47+
def push(self, el):
48+
heapq.heappush(self.data, PQElement(el))
49+
50+
def pop(self):
51+
return heapq.heappop(self.data)
52+
53+
def count(self):
54+
return len(self.data)
55+
2756
def top_k_frequent_1(nums, k):
2857
frequency = {}
2958

30-
# count the frequency of each element
59+
# count the frequency of each unique element
3160
for num in nums:
3261
if num in frequency:
3362
frequency[num] += 1
@@ -42,7 +71,17 @@ def top_k_frequent_1(nums, k):
4271
if k < 1:
4372
return []
4473

45-
# TODO: Implement Priority Queue and solve it
74+
heap = PriorityQueue()
75+
for el in arr:
76+
# push all elements
77+
heap.push(el)
78+
# pop the element with smallest frequency
79+
if heap.count() > k:
80+
heap.pop()
81+
82+
# take all elements from the heap
83+
# no need from K times heap.pop() (K LogK), because we already have the array with data (K)
84+
return [el.val for el in heap.data]
4685

4786

4887
##############
@@ -52,7 +91,7 @@ def top_k_frequent_1(nums, k):
5291
def top_k_frequent_2(nums, k):
5392
frequency = {}
5493

55-
# count the frequency of each element
94+
# count the frequency of each unique element
5695
for num in nums:
5796
if num in frequency:
5897
frequency[num] += 1
@@ -67,7 +106,7 @@ def top_k_frequent_2(nums, k):
67106
if k < 1:
68107
return []
69108

70-
# pivoting, find the first k element with the biggest frequency, O(U), U = num of unique nums
109+
# pivoting, find the first k elements with the biggest frequency, O(U), U = num of unique nums
71110
k -= 1
72111
left = 0
73112
right = n - 1
@@ -86,7 +125,7 @@ def top_k_frequent_2(nums, k):
86125
return None
87126

88127
def pivoting(arr, left, right):
89-
# O(N) pivoting
128+
# Linear time complexity pivoting
90129
# takes the last element as pivot
91130
pivot = right
92131
new_pivot = left
@@ -95,7 +134,7 @@ def pivoting(arr, left, right):
95134
# and put all elements bigger than the pivot (last element) in the first K spots
96135
# with the new_pivot we're "counting" how many bigger elements are there
97136
for j in range(left, right):
98-
if arr[j] > arr[pivot]:
137+
if arr[j][0] > arr[pivot][0]:
99138
swap(arr, new_pivot, j)
100139
new_pivot += 1
101140

0 commit comments

Comments
 (0)