class Solution:
    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
        """
        assuming all node val  are unique 
        tc O(N)  sc O(N)
        """
        seen = set()
        node = p 
        while node:
            seen.add(node.val)
            node = node.parent
        
        cur = q
        while cur:
            if cur.val in seen:
                return cur
            cur = cur.parent 
        return None 

optimization


class Solution:
    def lowestCommonAncestor(self, p: 'Node', q: 'Node') -> 'Node':
        """  tc O(H(p)+ H(q))  ==>O(N)   space O(1)
        ### assuming p,q both exist in the tree 
        
        take it like a linkedlist problem:  finding intersection of two linked list 
        tc O(N)  sc O(1)
        assuming q is LCA 
        p            q    root
        |-----x------|--y--|
        
        for q reach to root: distance y  == > set q  as x  +y  when q reach root:  total dis for q: x + 2 y 
        for p reach to root: distance x + y => set p  as y when q reach root:  total dis for p: x + 2 y at this moment, p and q has gone same distance=> pp == qq  
        
        from that on, pp and qq will have same parent node. which will be consider LCA 
        """
        pp,qq = p,q
        #cnt = 0
        while pp != qq:
            cnt += 1 
            pp = pp.parent if pp.parent else q
            qq = qq.parent if qq.parent else p
        #print(cnt)
        return pp