Heap Generic
Heap is a data structure that allows efficient access to the minimum (or maximum) element in a collection. It is commonly used to implement priority queues and sorting algorithms. In a generic heap, elements can be of any type, as long as a comparison function is provided to determine their relative ordering.
Let's implement a generic heap in Python using a min-heap as an example:
class Heap:
def __init__(self, comparison_fn):
self.heap = []
self.comparison_fn = comparison_fn
def parent(self, i):
return (i - 1) // 2
def left_child(self, i):
return 2 * i + 1
def right_child(self, i):
return 2 * i + 2
def swap(self, i, j):
self.heap[i], self.heap[j] = self.heap[j], self.heap[i]
def heapify_up(self, i):
while i > 0 and self.comparison_fn(self.heap[i], self.heap[self.parent(i)]):
parent = self.parent(i)
self.swap(i, parent)
i = parent
def heapify_down(self, i):
size = len(self.heap)
while True:
smallest = i
left = self.left_child(i)
right = self.right_child(i)
if left < size and self.comparison_fn(self.heap[left], self.heap[smallest]):
smallest = left
if right < size and self.comparison_fn(self.heap[right], self.heap[smallest]):
smallest = right
if smallest != i:
self.swap(i, smallest)
i = smallest
else:
break
def insert(self, value):
self.heap.append(value)
self.heapify_up(len(self.heap) - 1)
def extract_min(self):
if len(self.heap) == 0:
return None
min_value = self.heap[0]
self.swap(0, len(self.heap) - 1)
self.heap.pop()
self.heapify_down(0)
return min_value
Now, let's solve a LeetCode problem using the generic heap we implemented. The problem is "Kth Smallest Element in a Sorted Matrix," where we are given a matrix with each row and column sorted in ascending order, and we need to find the kth smallest element in the matrix.
def kthSmallest(matrix, k):
heap = Heap(lambda x, y: x[0] < y[0])
rows = len(matrix)
cols = len(matrix[0])
# Insert the first element from each row into the heap
for i in range(rows):
heap.insert((matrix[i][0], i, 0))
# Extract the minimum element k times
for _ in range(k - 1):
value, row, col = heap.extract_min()
# If the current element has a next element in its row, insert it into the heap
if col + 1 < cols:
heap.insert((matrix[row][col + 1], row, col + 1))
# The kth smallest element is the minimum element in the heap
return heap.extract_min()[0]
In this solution, we use the generic Heap
class to maintain a min-heap of tuples (value, row, col)
. We initially insert the first element from each row into the heap. Then, we iteratively extract the minimum element k - 1 times and insert the next element from the same row if it exists. Finally, we extract the minimum element, which gives us the kth smallest element in the matrix.
The time complexity of this solution is O(k log r), where r is the number of rows in the matrix. Since k is typically much smaller than the total number of elements in the matrix, this solution is efficient. The space complexity is O(r), as we only store at most one element from each row in the heap.
Here's an explanation of each function in the Heap
class for a min-heap:
__init__(self, comparison_fn)
: This is the constructor of theHeap
class. It initializes the heap list as an empty list and takes acomparison_fn
parameter, which is a function that compares two elements and returnsTrue
if the first element is smaller than the second element. This function is used to determine the ordering of the elements in the heap.parent(self, i)
: This function returns the index of the parent node given the indexi
of a node.left_child(self, i)
: This function returns the index of the left child node given the indexi
of a node.right_child(self, i)
: This function returns the index of the right child node given the indexi
of a node.swap(self, i, j)
: This function swaps the elements at indicesi
andj
in the heap.heapify_up(self, i)
: This function performs the "heapify up" operation, which ensures that the element at indexi
satisfies the heap property. It compares the element with its parent and swaps them if necessary, repeatedly moving up the heap until the heap property is satisfied.heapify_down(self, i)
: This function performs the "heapify down" operation, which ensures that the element at indexi
satisfies the heap property. It compares the element with its children and swaps it with the smallest child if necessary, repeatedly moving down the heap until the heap property is satisfied.insert(self, value)
: This function inserts a newvalue
into the heap. It appends the value to the end of the heap and then performs the heapify up operation to maintain the heap property.extract_min(self)
: This function extracts the minimum element from the heap, which is the root of the heap. It swaps the root with the last element in the heap, removes the last element, and then performs the heapify down operation to maintain the heap property.
These functions collectively provide the necessary operations to maintain a min-heap data structure. They ensure that the minimum element is always at the root of the heap and that inserting and extracting elements are done efficiently.