树中两个节点最低公共祖先系列算法
来源:互联网 发布:ansys软件 编辑:程序博客网 时间:2024/06/05 15:21
前言
最近刷到剑指offer 50题,树中两个结点的公共祖先,感觉这类题目对于不同性质的树会有不同的解法,而且也比较综合,在此就总结一下这类型的题目。
树为二叉搜索树
二叉搜索树的概念只要大家学过数据结构应该都是清楚的,也就是排序过的树。对于树上的每一个结点,其左子树的结点都小于父结点,其右子树的结点都大于父结点。那么我们解这道题的基本思想如下:
1)从根结点开始遍历,让其分别和输入的两个结点做比较。
2)如果当前结点比两个结点的值都大,那么最低公共祖先应该位于当前结点的左子树中。
3)如果当前结点比两个结点的值都小,那么最低公共祖先应该位于当前结点的右子树中。
4)如果当前结点在两个结点的值之间,那么最低公共祖先就是当前结点。
代码如下:
TreeNode* SameNode(TreeNode* pRoot,TreeNode *pNode1,TreeNode *pNode2){ if(pRoot==NULL||pNode1==NULL||pNode2==NULL) return NULL; int big=(pNode1->val>pNode2->val)?pNode1->val:pNode2->val; int small=(pNode1->val<pNode2->val)?pNode1->val:pNode2->val; TreeNode *res; if(big==small){ cout<<"Two Node should different "<<endl; return res; } if((small<pRoot->val)&&(big>pRoot->val)){ return pRoot; }else if((small<pRoot->val)&&(big<pRoot->val)){ res=SameNode(pRoot->left,pNode1,pNode2); }else if((small>pRoot->val)&&(big>pRoot->val)){ res=SameNode(pRoot->right,pNode1,pNode2); } return res;}
树为普通二叉树,有父指针
如果树中的每个结点,除根结点外,都有一个指向父结点的指针,那么这个问题就可以转换成求两个链表的第一个公共结点。例如假设树结点中指向父结点的指针是parent, 那么从树的每一个叶子结点开始都有一个由指针parent串起来的链表,这些链表的尾指针都是树的根结点。输入两个结点,那么这两个结点位于两个链表上,他们的最低公共祖先也就是两个链表的第一个公共结点。如输入D跟F,D所在的链表为D-B-A, F所在链表为F-C-A,所以最低公共祖先为A。代码如下:
int GetLength(TreeNode *pNode) { int len = 0; TreeNode *p = pNode; while (p != NULL) { len++; p = p->parent; } return len;}TreeNode *walkstep(TreeNode *pNode, int step) { while (step--) { pNode = pNode->parent; } return pNode;}TreeNode* SameNode(TreeNode* pRoot, TreeNode *pNode1, TreeNode *pNode2) { if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL) return NULL; int n1 = GetLength(pNode1); int n2 = GetLength(pNode2); if (n1>n2) { pNode1 = walkstep(pNode1, n1 - n2); } else { pNode2 = walkstep(pNode2, n2 - n1); } if (pNode1 == pNode2) { return pNode1->parent; } while (pNode1 != NULL) { if (pNode1 == pNode2) { return pNode1; } else { pNode1 = pNode1->parent; pNode2 = pNode2->parent; } } return NULL;}
树为普通二叉树,无父指针
在这样的情况下,我们可以首先利用前序遍历来得到根结点到某个结点的路径。当遍历两个得到输入结点的两条路径,问题转换成了求两个路径构成的链表的最后公共结点。代码如下:
#include <iostream>#include <vector>using namespace std;struct TreeNode { int val; TreeNode *left; TreeNode *right; TreeNode(int val) :val(val), left(NULL), right(NULL) {}};bool GetNodePath(TreeNode* pHead, TreeNode* pNode, vector<TreeNode*>& path){ if (pHead == pNode) return true; path.push_back(pHead); bool found = false; if (pHead->left != NULL) found = GetNodePath(pHead->left, pNode, path); if (!found && pHead->right) found = GetNodePath(pHead->right, pNode, path); if (!found) path.pop_back(); return found;}TreeNode *GetLastCommonNode(const vector<TreeNode*> &path1, const vector<TreeNode*> &path2) { vector<TreeNode*>::const_iterator it1 = path1.begin(); vector<TreeNode*>::const_iterator it2 = path2.begin(); TreeNode *plast = NULL; while (it1 != path1.end() && it2 != path2.end()) { if (*it1 == *it2) { plast = *it1; } it1++; it2++; } return plast;}TreeNode* SameNode(TreeNode* pRoot, TreeNode *pNode1, TreeNode *pNode2) { if (pRoot == NULL || pNode1 == NULL || pNode2 == NULL) return NULL; vector<TreeNode*> path1; GetNodePath(pRoot, pNode1, path1); vector<TreeNode*> path2; GetNodePath(pRoot, pNode2, path2); return GetLastCommonNode(path1, path2);}int main() { /* // // 4 // / \ // 2 6 // / \ / \ // 1 3 5 7 */ TreeNode *n1 = new TreeNode(1); TreeNode *n2 = new TreeNode(2); TreeNode *n3 = new TreeNode(3); TreeNode *n4 = new TreeNode(4); TreeNode *n5 = new TreeNode(5); TreeNode *n6 = new TreeNode(6); TreeNode *n7 = new TreeNode(7); n4->left = n2; n4->right = n6; n2->left = n1; n2->right = n3; n6->left = n5; n6->right = n7; TreeNode *res = SameNode(n4, n1, n3); cout << res->val << endl; // 8 // / // 9 // / // 10 // / // 11 // / // 12 TreeNode *n8 = new TreeNode(8); TreeNode *n9 = new TreeNode(9); TreeNode *n10 = new TreeNode(10); TreeNode *n11 = new TreeNode(11); TreeNode *n12 = new TreeNode(12); n8->left = n9; n9->left = n10; n10->left = n11; n11->left = n12; TreeNode *res1 = SameNode(n8, n9, n10); cout << res1->val << endl;}
总结
在求树的相关问题中,我们在找不到思路的时候,可以尝试着让树转换成链表的相关问题,再尝试着去解决,说不定这里会有喷火龙!
阅读全文
0 0
- 树中两个节点最低公共祖先系列算法
- 树中两个节点的最低公共祖先
- 树中两个节点的最低公共祖先
- 找出树中两个节点的最低公共祖先
- 二叉树中查找两个节点的最低公共祖先
- 树中两个节点的最低公共祖先
- 剑指offer-树中两个节点的最低公共祖先
- 求二叉树中两个节点的最低公共祖先
- 二叉树中两个节点的最低公共祖先
- 树中两个节点的最低公共祖先
- 剑指offer-树中两个节点的最低公共祖先
- 求二叉树中两个节点的最低公共祖先
- 查找树中两个节点的最低公共祖先
- 树中两个节点的最低公共祖先(剑指offer)
- LCA树两个节点最低公共祖先
- 算法:寻找树中两个结点的最低公共祖先
- 算法题目---树中两个结点的最低公共祖先
- 树中节点最低公共祖先
- Java Socket网络编程(一)
- Android 图片处理 部分案例整理
- Vue学习笔记八
- 利用mybatis-generator自动生成代码
- 第八节:SpringBoot集成MyBatis
- 树中两个节点最低公共祖先系列算法
- 【SAP干货】创建Search Helps (Elementary and Secondary)
- (转)[Android] 防止连续点击打开两个重复页面的小技巧
- 面试必懂之数组排序法总结
- 特征分解、奇异值分解、PCA(个人理解)
- Oracle 更改表名称的几种方式
- 组合模式
- Android精确判断是否为64位
- 【矩阵快速幂 && 循环节】HDU