leetcode 236 二叉树的最近公共祖先

Posted xianbin7

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了leetcode 236 二叉树的最近公共祖先相关的知识,希望对你有一定的参考价值。

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”

例如,给定如下二叉树:  root = [3,5,1,6,2,0,8,null,null,7,4]

 Java solution1 

  static  int BOTH_PENDING = 2;
    static  int LEFT_DONE = 1;
    static  int BOTH_DOWN = 0;
    public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q) 
        Stack<Pair<TreeNode , Integer >>   stack = new Stack<>();
        stack.push(new Pair<TreeNode, Integer>(root, BOTH_PENDING));

        boolean one_node_found = false;
        TreeNode LCA = null;
        while(!stack.empty())
            Pair<TreeNode, Integer> pair = stack.peek();
            TreeNode parentNode = pair.getKey();
            int      parentState = pair.getValue();
            if( parentState != BOTH_DOWN)
                TreeNode childNode ;
                if( parentState == BOTH_PENDING)
                    if( parentNode == p || parentNode == q)
                         if(one_node_found)
                               return LCA;
                         
                         else
                            one_node_found = true;
                            LCA = stack.peek().getKey();
                         
                    
                    childNode = parentNode.left;
                
                else
                    childNode = parentNode.right;
                
                stack.pop();
                stack.push(new Pair<TreeNode, Integer>(parentNode, parentState -1 ));
                if(childNode != null)
                    stack.push(new Pair<TreeNode, Integer>(childNode, BOTH_PENDING));
                
            
            else
               if(LCA == stack.pop().getKey() && one_node_found)
                   LCA = stack.peek().getKey();
               
            
        
        return LCA;
    

Java Solution2 

 public TreeNode lowestCommonAncestor2(TreeNode root, TreeNode p, TreeNode q) 
        if(root == null)
            return root;
        
        if(root == p || root == q)
            return root;
        
        TreeNode  left = lowestCommonAncestor2(root.left , p,q);
        TreeNode  right = lowestCommonAncestor2(root.right, p, q);
        if(left !=null && right !=null)
            return root;
        
        else if(left !=null)
            return left;
        
        else if(right != null)
            return right;
        
        return null;
    
# Definition for a binary tree node.
class TreeNode:
    def __init__(self, x):
        self.val = x
        self.left = None
        self.right = None
# my solution
# class Solution:
#     def dfs(self, root: ‘TreeNode‘, p: ‘TreeNode‘ , stack: list) :
#         if( root == None):
#             return None
#         if(root == p ):
#             stack.append(root)
#             return True
#         ans = False
#         if( root.left != None):
#             stack.append(root)
#             ans = self.dfs(root.left,p,  stack)
#             if(not ans):
#                  stack.pop(-1)
#             else:
#                 return ans
#         if ( root.right != None):
#             stack.append(root)
#             ans = self.dfs(root.right,p,  stack)
#             if(not ans):
#                  stack.pop(-1)
#             else:
#                 return ans
#
#         return ans
#
#     def lowestCommonAncestor(self, root: ‘TreeNode‘, p: ‘TreeNode‘, q: ‘TreeNode‘) -> ‘TreeNode‘:
#         p_stack = []
#         self.dfs(root, p,p_stack)
#         q_stack = []
#         self.dfs(root, q,q_stack)
#
#         p_stack.reverse()
#         q_stack.reverse()
#         for i_node in p_stack:
#             for j_node in q_stack:
#                 if( i_node.val == j_node.val ):
#                     return i_node

# 方法一:递归
# class Solution:
#     def __init__(self):
#         self.ans = None
#
#     def lowestCommonAncestor(self, root, p, q):
#         def recurse_tree(current_node):
#             if not current_node:
#                 return False
#             left = recurse_tree( current_node.left)
#             right = recurse_tree( current_node.right)
#             mid = current_node == p or current_node == q
#             if( mid + left + right >= 2):
#                 self.ans = current_node
#             return mid or left or right
#         recurse_tree(root)
#         return self.ans

def pre_order_receverse(root : TreeNode):
    stack = []
    pNode = root
    while( pNode != None or len(stack) > 0 ):
        if( pNode != None ):
            print(pNode.val)

            pNode =  pNode.left
        else:
            node = stack.pop()
            stack.append(pNode)
            pNode = node.right

def dfs_order_receverse(root : TreeNode):
    stack = [root]
    # pNode = root
    while( len(stack) > 0 ):
        pNode = stack.pop(-1)
        print(pNode.val)
        if( pNode.right != None  ):
            stack.append(pNode.right)
        if( pNode.left != None  ):
            stack.append(pNode.left)

# 方法二:使用父指针迭代
# class Solution:
#     def lowestCommonAncestor(self, root, p, q):
#         stack = []
#         parent = 
#         parent[root] = None
#         stack.append(root)
#         while p not in parent or q not in parent:
#             node = stack.pop(-1)
#             if(node.left ):
#                 parent[node.left] = node
#                 stack.append(node.left)
#             if(node.right):
#                 parent[node.right] = node
#                 stack.append(node.right)
#         ancestor = set()
#         while(p):
#             ancestor.add(p);
#             p = parent[p]
#         while( q not in ancestor):
#             q =  parent[q]
#         return  q

# 方法三 无父指针的迭代
class Solution:

    # Three static flags to keep track of post-order traversal.

    # Both left and right traversal pending for a node.
    # Indicates the nodes children are yet to be traversed.
    BOTH_PENDING = 2
    # Left traversal done.
    LEFT_DONE = 1
    # Both left and right traversal done for a node.
    # Indicates the node can be popped off the stack.
    BOTH_DONE = 0

    def lowestCommonAncestor(self, root, p, q):

        stack = [(root, Solution.BOTH_PENDING)]
        one_node_found = False
        LCA_index = -1
        while stack:
            parent_node, parent_state = stack[-1]
            if parent_state != Solution.BOTH_DONE:
                if parent_state == Solution.BOTH_PENDING:
                    if parent_node == p or parent_node == q:
                        if one_node_found:
                            return stack[LCA_index][0]
                        else:
                            one_node_found = True
                            LCA_index = len(stack) - 1
                    child_node = parent_node.left
                else:
                    child_node = parent_node.right
                stack.pop()
                stack.append((parent_node, parent_state - 1))
                if child_node:
                    stack.append((child_node, Solution.BOTH_PENDING))
            else:
                if one_node_found and LCA_index == len(stack) - 1:
                    LCA_index -= 1
                stack.pop()

        return None


if __name__ == __main__:
    root = TreeNode(3)
    node1 = TreeNode(5)
    node2 = TreeNode(1)
    node3 = TreeNode(6)
    node4 = TreeNode(2)
    node5 = TreeNode(0)
    node6 = TreeNode(8)
    node7 = TreeNode(7)
    node8 = TreeNode(4)

    root.left = node1
    root.right = node2
    node1.left = node3
    node1.right = node4
    node2.left = node5
    node2.right = node6
    node4.left = node7
    node4.right = node8

    p = node1
    q = node2
    # dfs_order_receverse(root)
    print( Solution().lowestCommonAncestor(root, p, q).val )

 

 Java solution1 

以上是关于leetcode 236 二叉树的最近公共祖先的主要内容,如果未能解决你的问题,请参考以下文章

Leetcode 236.二叉树的最近公共祖先

leetcode 236 二叉树的最近公共祖先

leetcode 236. 二叉树的最近公共祖先

leetcode-236二叉树的最近公共祖先

leetcode 236 二叉树的最近公共祖先

Leetcode-236. 二叉树的最近公共祖先