Programmer interview question 5: minimum common parent node of two binary nodes

Source: Internet
Author: User

Question: The Node definition of a binary tree is as follows:

Struct treenode

{

Int m_nvalue;

Treenode * m_pleft;

Treenode * m_pright;

};

Input two nodes in the binary tree and output the lowest common parent node among the two nodes.

Analysis: finding the lowest common node between the two nodes is a common problem during the interview. This problem has at least two variants.

The first variant is that a binary tree is a special Binary Tree: search for a binary tree. That is, the tree is sorted. The nodes on the left subtree are smaller than those on the parent node, while those on the right subtree are larger than those on the parent node. We only need to compare the two nodes from the root node. If the value of the current node is greater than that of the two nodes, the lowest common parent node must be in the left subtree of the current node. If the value of the current node is smaller than that of the two nodes, the lowest common parent node must be in the right subtree of the current node.

The second variant is that the tree is not necessarily a binary tree, and each node has a pointer pointing to its parent node. So we can start from any node and get a one-way linked list that reaches the root node. Therefore, this problem is converted to the first public node of two one-way linked lists.

Now let's go back to this issue. The so-called common parent node is that both nodes appear in the Child tree of this node. Therefore, we can define a function to determine whether a node's subtree contains another node. This is not a very difficult task. We can implement it using recursive methods:

/*// If the tree with head pHead has a node pNode, return true.// Otherwise return false.*/bool HasNode(TreeNode* pHead, TreeNode* pNode){if(pHead == pNode)return true;bool has = false;if(pHead->m_pLeft != NULL)has = HasNode(pHead->m_pLeft, pNode);if(!has && pHead->m_pRight != NULL)has = HasNode(pHead->m_pRight, pNode);return has;}

We can start from the root node and determine whether the left and right subtree of the tree with the current node as the root contains the two nodes we are looking. If both nodes appear in its left subtree, the lowest common parent node also appears in its left subtree. If both nodes appear in its right subtree, the lowest common parent node also appears in its right subtree. If one of the two nodes appears in the left subtree and the other appears in the right subtree, the current node is the lowest common parent node. Based on this idea, we can write the following code:

/*// Find the last parent of pNode1 and pNode2 in a tree with head pHead*/TreeNode* LastCommonParent_1(TreeNode* pHead, TreeNode* pNode1, TreeNode* pNode2){if(pHead == NULL || pNode1 == NULL || pNode2 == NULL)return NULL;// check whether left child has pNode1 and pNode2bool leftHasNode1 = false;bool leftHasNode2 = false;if(pHead->m_pLeft != NULL){leftHasNode1 = HasNode(pHead->m_pLeft, pNode1);leftHasNode2 = HasNode(pHead->m_pLeft, pNode2);} if(leftHasNode1 && leftHasNode2){if(pHead->m_pLeft == pNode1 || pHead->m_pLeft == pNode2)return pHead;return LastCommonParent_1(pHead->m_pLeft, pNode1, pNode2);}// check whether right child has pNode1 and pNode2bool rightHasNode1 = false;bool rightHasNode2 = false;if(pHead->m_pRight != NULL){if(!leftHasNode1)rightHasNode1 = HasNode(pHead->m_pRight, pNode1);if(!leftHasNode2)rightHasNode2 = HasNode(pHead->m_pRight, pNode2);}if(rightHasNode1 && rightHasNode2){if(pHead->m_pRight == pNode1 || pHead->m_pRight == pNode2)return pHead;return LastCommonParent_1(pHead->m_pRight, pNode1, pNode2);}if((leftHasNode1 && rightHasNode2) || (leftHasNode2 && rightHasNode1))return pHead; return NULL;}

Next, let's analyze the efficiency of this method. The essence of the hasnode function is to traverse a tree. Its time complexity is O (n) (N is the number of nodes in the tree ). Since we start with the root node, we need to call the hasnode function for each node. Therefore, the total time complexity is O (n ^ 2 ).

By carefully analyzing the above code, we can easily find that we need to traverse every node of the tree to determine whether a node-based tree contains a node. Next, we can determine whether the tree with the Left or Right node as the root contains the node to be searched. We still need to traverse it. The second traversal operation was actually done before the first traversal. Due to repeated traversal, the time efficiency of this method is definitely not the best.

We mentioned earlier that if there is a pointer to the parent node in the node, we can convert the problem into finding the common nodes of the two linked lists. Now we can find a way to get this linked list. Here we can make a slight change:

/*// Get the path form pHead and pNode in a tree with head pHead*/bool GetNodePath(TreeNode* pHead, TreeNode* pNode, std::list<TreeNode*>& path){if(pHead == pNode)return true; path.push_back(pHead); bool found = false;if(pHead->m_pLeft != NULL)found = GetNodePath(pHead->m_pLeft, pNode, path);if(!found && pHead->m_pRight)found = GetNodePath(pHead->m_pRight, pNode, path);if(!found)path.pop_back();return found;}

This path starts from the heel node. The lowest common parent node is the last common node in the path:

/*// Get the last common Node in two lists: path1 and path2*/TreeNode* LastCommonNode( const std::list<TreeNode*>& path1,  const std::list<TreeNode*>& path2 ){std::list<TreeNode*>::const_iterator iterator1 = path1.begin();std::list<TreeNode*>::const_iterator iterator2 = path2.begin();   TreeNode* pLast = NULL;while(iterator1 != path1.end() && iterator2 != path2.end()){if(*iterator1 == *iterator2)pLast = *iterator1;iterator1++;iterator2++;}return pLast;}

With the first two subfunctions, it is easy to find the lowest common parent node of the two nodes. We first find the two paths from the root node to the two nodes, and then find the last common node of the two paths. The Code is as follows:

/*// Find the last parent of pNode1 and pNode2 in a tree with head pHead*/TreeNode* LastCommonParent_2(TreeNode* pHead, TreeNode* pNode1, TreeNode* pNode2){if(pHead == NULL || pNode1 == NULL || pNode2 == NULL)return NULL;std::list<TreeNode*> path1;GetNodePath(pHead, pNode1, path1);std::list<TreeNode*> path2;GetNodePath(pHead, pNode2, path2);return LastCommonNode(path1, path2);}

The time complexity of this approach is O (n), and the time efficiency is much better than the first method. However, we should also note that this idea requires two linked lists to store the path, which is less efficient than the first method.

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.