Here is my code to use range minimal query to resolve the LCA problem. Any advice on code bugs, performance improvement in terms of algorithm time complexity, code style are appreciated.
More specifically, my questions are:
- I am using in-order traverse to build depth array. Should I use other traverse, like pre-order (dfs), level-order, or post order?
- I am using two additional data structures,
index_node_map
andnode_index_map
. I'm wondering if there are any ways to remove them, as they make my code seem lengthy.
Major ideas of my idea are:
- Build depth array of each node by in-order traverse
- Build MRQ index for depth array built in first step
- For any two nodes, their LCA are the lowest depth node between them (in depth array)
from collections import defaultdict
class TreeNode:
def __init__(self, value, left, right):
self.value = value
self.left = left
self.right = right
class Solution:
def __init__(self):
self.index_node_map = defaultdict(int)
self.node_index_map = defaultdict(int)
self.depth = []
self.rmp_map = defaultdict(tuple) # key: (index, step), value: (min value, index)
def in_order(self, root, level):
if root.left:
self.in_order(root.left, level+1)
self.depth.append(level)
self.index_node_map[len(self.depth)-1]=root.value
self.node_index_map[root.value] = len(self.depth)-1
if root.right:
self.in_order(root.right, level+1)
def build_depth_index(self, root, level):
self.in_order(root, level)
print self.depth
print self.index_node_map
print self.node_index_map
self.build_rmq_map(self.depth)
def build_rmq_map(self, result):
step = len(result).bit_length()
for i in range(len(result)):
self.rmp_map[(i,0)]=(result[i],i)
for s in range(1, step+1):
for i in range(len(result)):
if i + 2 **(s-1) < len(result):
self.rmp_map[(i,s)] = min(self.rmp_map[(i,s-1)],self.rmp_map[(i+2**(s-1),s-1)])
else:
self.rmp_map[(i,s)] = self.rmp_map[(i, s-1)]
def rmp_query(self, index1, index2):
step = (index2 - index1).bit_length()-1
x = self.rmp_map[(index1, step)]
y = self.rmp_map[(index2+1-2**(step), step)]
# return index of depth array min value
if x[0] < y[0]:
return x[1]
else:
return y[1]
def lca_query(self, node1, node2):
index1 = self.node_index_map[node1]
index2 = self.node_index_map[node2]
min_index = self.rmp_query(index1, index2)
return self.index_node_map[min_index]
if __name__ == "__main__":
root = TreeNode(1, TreeNode(2, TreeNode(4, None, None), TreeNode(5, None, None)), TreeNode(3, TreeNode(6, None, None),TreeNode(7,None,None)))
s = Solution()
s.build_depth_index(root, 0)
print s.lca_query(4,5)
print s.lca_query(4, 7)