Reputation: 11
So I was trying to implement LCA using Euler tour and RMQ with Sparse Table in python. My code is working fine, if I insert number from left side of the tree. The code for building the tree is:
The node class has data, left_child and right_child:
class Node:
def __init__(self, value):
self.data = value
self.right_child = None
self.left_child = None
Then I have a tree class which I used to build the tree:
class Tree:
content = []
def __init__(self):
self.root = None
def add_child(self, arr, root, i, n):
if i < n:
temp = Node(arr[i])
root = temp
root.left_child = self.add_child(arr, root.left_child, 2 * i + 1, n)
root.right_child = self.add_child(arr, root.right_child, 2 * i + 2, n)
return root
def pre_order(self, root):
if root != None:
Tree.content.append(root.data)
self.pre_order(root.left_child)
self.pre_order(root.right_child)
return Tree.content
Finally, I got an LCA class which mainly contains the function for building the sparse table, then do a RMQ on the sparse table, then a function that does the part of the euler tour and finally the function for finding LCA.
class LCA:
def __init__(self, root, length):
self.pre_process_array = [[0] * (math.floor(math.log2(length) + 2)) for _ in range((length * 2) - 1)]
self.euler = [0] * (length * 2 - 1)
self.height = [0] * (length * 2 - 1)
self.index = [-1 for _ in range(length + 1)]
self.tour = 0
self.euler_tour(root, 0)
self.build_sparse_table(self.height)
print(self.pre_process_array)
def build_sparse_table(self, height_array):
for i in range(len(height_array)):
self.pre_process_array[i][0] = height_array[i]
j = 1
while (1 << j) <= len(height_array):
i = 0
while (i + (1 << j) - 1) < len(height_array):
if self.pre_process_array[i][j - 1] < self.pre_process_array[i + (1 << (j - 1))][j-1]:
self.pre_process_array[i][j] = self.pre_process_array[i][j - 1]
else:
self.pre_process_array[i][j] = self.pre_process_array[i + (1 << (j - 1))][j - 1]
i += 1
j += 1
def rmq(self, l, h):
j = int(math.log2(h - l + 1))
if self.pre_process_array[l][j] <= self.pre_process_array[h - (1 << j) + 1][j]:
return self.pre_process_array[l][j]
else:
return self.pre_process_array[h - (1 << j) + 1][j]
def euler_tour(self, root, level):
if root is not None:
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
if self.index[root.data] == -1:
self.index[root.data] = self.tour - 1
if root.left_child is not None:
self.euler_tour(root.left_child, level + 1)
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
if root.right_child is not None:
self.euler_tour(root.right_child, level + 1)
self.euler[self.tour] = root.data
self.height[self.tour] = level
self.tour += 1
def find_LCA(self, val1, val2):
if val1 >= len(self.index) or val2 >= len(self.index) or self.index[val1] == -1 or self.index[val2] == -1:
return -1
if self.index[val1] > self.index[val2]:
return self.euler[self.rmq(self.index[val2], self.index[val1])]
elif self.index[val2] > self.index[val1]:
return self.euler[self.rmq(self.index[val1], self.index[val2])]
And my driver code is as follow:
tree_data = [1,2,3,4,5,6,7,8,9]
length = len(tree_data)
tree = Tree()
root = tree.root
tree.root = tree.add_child(tree_data, root, 0, length)
l = LCA(tree.root, length)
print(l.find_LCA(6, 3))
so, my tree should something look like:
1
/ \
2 3
/ \ / \
4 5 6 7
/ \
8 9
Now, if I try to find the LCA(8, 9) or LCA(4, 3), I get the correct output but whenever I try to give LCA(6, 7) or LCA(3, 7), It always keeps returning 2 as the answer where it should return 3 and 3 respectively.
I don't have any idea where is the mistake as, from my side it looks pretty fine.
Upvotes: 1
Views: 48