-
Notifications
You must be signed in to change notification settings - Fork 90
/
Lowest Common Ancestor.py
114 lines (85 loc) · 2.72 KB
/
Lowest Common Ancestor.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
"""
Given the root and two nodes in a Binary Tree. Find the lowest common ancestor(LCA) of the two nodes.
The lowest common ancestor is the node with largest depth which is the ancestor of both nodes.
Example
4
/ \
3 7
/ \
5 6
For 3 and 5, the LCA is 4.
For 5 and 6, the LCA is 7.
For 6 and 7, the LCA is 7.
"""
__author__ = 'Danyang'
class TreeNode:
def __init__(self, val):
self.val = val
self.left, self.right = None, None
def __repr__(self):
return repr(self.val)
class Solution:
def lowestCommonAncestor(self, root, A, B):
"""
O(n) for find path
...>LCA***>A
...>LCA####>B
Any node on two paths before LCA are equal respectively
Any node on two paths after LCA are different respectively
1. get the paths from root to A and from root to B
2. cut longer path's tail to make two equal length
3. scan backward to find the first common ancestor
:type root: TreeNode
:type A: TreeNode
:type B: TreeNode
:param root: The root of the binary search tree.
:param A: node in a Binary.
:param B: node
:return: Return the least common ancestor(LCA) of the two nodes.
"""
p1 = self.path(root, A)
p2 = self.path(root, B)
p1.append(TreeNode(0)) # dummy
p2.append(TreeNode(0)) # dummy
for ind, val in enumerate(p1):
if val != p2[ind]:
return p1[ind-1]
def path(self, root, target):
"""
path from root to target
:param target:
:return:
"""
ans = []
self.get_path(root, target, [], ans)
return ans
def get_path(self, cur, target, path, ans):
"""
:param cur:
:param target:
:param path:
:param ans:
:return: bool
"""
if not cur:
return False
path.append(cur)
if cur == target: # compare by reference
# ans = path
ans.extend(path) # otherwise lose reference
return True
if cur.left and self.get_path(cur.left, target, path, ans):
return True
if cur.right and self.get_path(cur.right, target, path, ans):
return True
path.pop()
return False
if __name__ == "__main__":
node = TreeNode(1)
print Solution().lowestCommonAncestor(node, node, node)
nodes = dict(zip(range(3, 8), [TreeNode(i) for i in range(3, 8)]))
nodes[4].left = nodes[3]
nodes[4].right = nodes[7]
nodes[7].left = nodes[5]
nodes[7].right = nodes[6]
print Solution().lowestCommonAncestor(nodes[4], nodes[3], nodes[5])