1+ class Solution (object ):
2+ def lowestCommonAncestor (self , root , p , q ):
3+ p_ancestor = []
4+ q_ancestor = []
5+
6+ stack = []
7+ stack .append ((root , []))
8+ while stack :
9+ node , path = stack .pop ()
10+ if node is p : p_ancestor = path + [p ]
11+ if node is q : q_ancestor = path + [q ]
12+ if p_ancestor and q_ancestor : break #[0]
13+ if node .left : stack .append ((node .left , path + [node ]))
14+ if node .right : stack .append ((node .right , path + [node ]))
15+
16+ if len (p_ancestor )> len (q_ancestor ): #[1]
17+ s = set (q_ancestor )
18+ for node in reversed (p_ancestor ): #[2]
19+ if node in s : return node #[3]
20+ else : #[1]
21+ s = set (p_ancestor )
22+ for node in reversed (q_ancestor ): #[2]
23+ if node in s : return node #[3]
24+ return None
25+
26+
27+
28+ class Solution (object ):
29+ def lowestCommonAncestor (self , root , p , q ):
30+ def helper (node ):
31+ if not node : return False
32+ l , r = helper (node .left ), helper (node .right )
33+ curr = node is p or node is q
34+ if (int (l )+ int (r )+ int (curr ) >= 2 ): self .ans = node
35+ return l or r or curr
36+
37+ self .ans = None
38+ helper (root )
39+ return self .ans
40+
41+
42+
43+ class Solution (object ):
44+ def lowestCommonAncestor (self , root , p , q ):
45+ stack = []
46+ stack .append (root )
47+
48+ parent = {}
49+ parent [root ] = None
50+
51+ while p not in parent or q not in parent :
52+ node = stack .pop ()
53+ if node .left :
54+ parent [node .left ] = node
55+ stack .append (node .left )
56+ if node .right :
57+ parent [node .right ] = node
58+ stack .append (node .right )
59+
60+ p_ancestor = p
61+ q_ancestor = q
62+ p_ancestors = set ()
63+ while p_ancestor :
64+ p_ancestors .add (p_ancestor )
65+ p_ancestor = parent [p ]
66+ while q_ancestor :
67+ if q_ancestor in p_ancestors : return q_ancestor
68+ q_ancestor = parent [q ]
69+
70+ return None
71+
72+
73+ #2020/7/11
74+ class Solution (object ):
75+ def lowestCommonAncestor (self , root , p , q ):
76+ def find_genealogy ():
77+ genealogy = {}
78+ stack = []
79+ stack .append (root )
80+ p_found = q_found = False
81+ while stack :
82+ node = stack .pop ()
83+ if node .left :
84+ genealogy [node .left ] = node
85+ stack .append (node .left )
86+ if node .right :
87+ genealogy [node .right ] = node
88+ stack .append (node .right )
89+
90+ if node is p : p_found = True
91+ if node is q : q_found = True
92+ if p_found and q_found : break
93+ return genealogy
94+
95+ def find_ancestors (target , genealogy ):
96+ ancestors = []
97+ curr_node = target
98+ while curr_node :
99+ ancestors .append (curr_node )
100+ curr_node = genealogy [curr_node ] if curr_node in genealogy else None
101+ return ancestors
102+
103+ def find_lowest_common (a1 , a2 ):
104+ if len (a1 )> len (a2 ):
105+ a2 = set (a2 )
106+ for node in a1 :
107+ if node in a2 :
108+ return node
109+ else :
110+ a1 = set (a1 )
111+ for node in a2 :
112+ if node in a1 :
113+ return node
114+
115+ genealogy = find_genealogy ()
116+ p_ancestors = find_ancestors (p , genealogy )
117+ q_ancestors = find_ancestors (q , genealogy )
118+ return find_lowest_common (p_ancestors , q_ancestors )
119+
120+ """
121+ The idea is simple
122+ Find all the ancestors of `p` and `q`.
123+ To find ancestors of `p` and `q`, we need to generate a `genealogy`, where we can find the parant of each node. (genealogy[child] = parant)
124+ After that, we see if the lowest node exist in both `p_ancestor` and `q_ancestor`.
125+ To make sure we start from the lowest node, we need to start from the larger `p_ancestor` or `q_ancestor`.
126+
127+ Time complexity: O(N).
128+ find_genealogy() is O(N), because we use DFS to travel all nodes.
129+ find_ancestors() is O(LogN).
130+ find_lowest_common is O(LogN).
131+ Space complexity is O(N), since `genealogy` may carry all the nodes.
132+ """
0 commit comments