二叉树两结点的最低共同父结点
2012-07-07 16:27
197 查看
题目:二叉树的结点定义如下:
输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。
分析:求数中两个结点的最低共同结点是面试中经常出现的一个问题。这个问题至少有两个变种。
第一变种是二叉树是一种特殊的二叉树:查找二叉树。也就是树是排序过的,位于左子树上的结点都比父结点小,而位于右子树的结点都比父结点大。我们只需要从根结点开始和两个结点进行比较。如果当前结点的值比两个结点都大,则最低的共同父结点一定在当前结点的左子树中。如果当前结点的值比两个结点都小,则最低的共同父结点一定在当前结点的右子树中。
第二个变种是树不一定是二叉树,每个结点都有一个指针指向它的父结点。于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点。我们在本面试题系列的第35题讨论了这个问题。
前面我们提过如果结点中有一个指向父结点的指针,我们可以把问题转化为求两个链表的共同结点。现在我们可以想办法得到这个链表。我们在本面试题系列的第4题中分析过如何得到一条中根结点开始的路径。我们在这里稍作变化即可:
由于这个路径是从跟结点开始的。最低的共同父结点就是路径中的最后一个共同结点:
有了前面两个子函数之后,求两个结点的最低共同父结点就很容易了。我们先求出从根结点出发到两个结点的两条路径,再求出两条路径的最后一个共同结点。代码如下:
这种思路的时间复杂度是O(n),时间效率要比第一种方法好很多。但同时我们也要注意到,这种思路需要两个链表来保存路径,空间效率比较低。
以上转自何海涛博客
要求两节点的最近共同父节点(LCA,lowest common ancestor),可以采用树的后序遍历。如果这两个节点不在一条线上,则它们必定分别在所求节点A的左子树和右子树上,后序遍历到第一个满足这个条件的节点就是所要求的节点A。另外,当这两个节点在一条线上,所求节点A则是这两个节点中层次最低的节点的父节点。
以上转自flyinghearts
struct TreeNode { int m_nvalue; TreeNode* m_pLeft; TreeNode* m_pRight; };
输入二叉树中的两个结点,输出这两个结点在数中最低的共同父结点。
分析:求数中两个结点的最低共同结点是面试中经常出现的一个问题。这个问题至少有两个变种。
第一变种是二叉树是一种特殊的二叉树:查找二叉树。也就是树是排序过的,位于左子树上的结点都比父结点小,而位于右子树的结点都比父结点大。我们只需要从根结点开始和两个结点进行比较。如果当前结点的值比两个结点都大,则最低的共同父结点一定在当前结点的左子树中。如果当前结点的值比两个结点都小,则最低的共同父结点一定在当前结点的右子树中。
第二个变种是树不一定是二叉树,每个结点都有一个指针指向它的父结点。于是我们可以从任何一个结点出发,得到一个到达树根结点的单向链表。因此这个问题转换为两个单向链表的第一个公共结点。我们在本面试题系列的第35题讨论了这个问题。
前面我们提过如果结点中有一个指向父结点的指针,我们可以把问题转化为求两个链表的共同结点。现在我们可以想办法得到这个链表。我们在本面试题系列的第4题中分析过如何得到一条中根结点开始的路径。我们在这里稍作变化即可:
///////////////////////////////////////////////////////////////////////////////// // 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; }
由于这个路径是从跟结点开始的。最低的共同父结点就是路径中的最后一个共同结点:
///////////////////////////////////////////////////////////////////////////////// // 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; }
有了前面两个子函数之后,求两个结点的最低共同父结点就很容易了。我们先求出从根结点出发到两个结点的两条路径,再求出两条路径的最后一个共同结点。代码如下:
///////////////////////////////////////////////////////////////////////////////// // 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); }
这种思路的时间复杂度是O(n),时间效率要比第一种方法好很多。但同时我们也要注意到,这种思路需要两个链表来保存路径,空间效率比较低。
以上转自何海涛博客
要求两节点的最近共同父节点(LCA,lowest common ancestor),可以采用树的后序遍历。如果这两个节点不在一条线上,则它们必定分别在所求节点A的左子树和右子树上,后序遍历到第一个满足这个条件的节点就是所要求的节点A。另外,当这两个节点在一条线上,所求节点A则是这两个节点中层次最低的节点的父节点。
static bool lca(Node *root, int va, int vb, Node *&result, Node* parrent) { // left/right 左/右子树是否含有要判断的两节点之一 bool left = false, right = false; if (!result && root->left) left = lca(root->left,va,vb,result,root); if (!result && root->right) right = lca(root->right,va,vb,result,root); // mid 当前节点是否是要判断的两节点之一 bool mid = false; if (root->data == va || root->data == vb) mid=true; if (!result && int(left + right + mid) == 2) { if (mid) result = parrent; else result = root; } return left | mid | right ; } Node *lca(Node *root,int va, int vb) { if (root == NULL) return NULL; Node *result = NULL; lca(root, va, vb,result, NULL); return result; }
以上转自flyinghearts
相关文章推荐
- 二叉树两结点的最低共同父结点
- 程序员面试100题之五:二叉树两个结点的最低共同父结点
- 程序员面试题精选100题(48)-二叉树两个结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 二叉树两结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 程序员面试题精选100题(48)-二叉树两结点的最低共同父结点[数据结构]
- 程序员面试题精选100题(48)-二叉树两结点的最低共同父结点
- 程序员面试100题之五:二叉树两个结点的最低共同父结点
- [二叉树]二叉树两个结点的最低共同父结点
- 二叉树两结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 深入二叉树两个结点的最低共同父结点的详解
- 二叉树两个结点的最低共同父结点(树)
- 面试训练二叉树两结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 二叉树两结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 二叉树两个结点的最低共同父结点
- 【编程题目】二叉树两个结点的最低共同父结点