探析求树中两个节点p和q的最低公共祖先

来源:互联网 发布:手机淘宝怎么放优惠券 编辑:程序博客网 时间:2024/06/06 05:55

题目


树中两个节点的最低公共祖先。

分析


描述十分简洁的题目,其实有多种变体;
我们从4种情况来讨论:
  1. 情况1,在二叉搜索树中找节点p和q的最低公共祖先
  2. 情况2,非二叉搜索树,只是普通的二叉树,树中每个节点包含指向父节点的指针
  3. 情况3,非二叉搜索树,只是普通的二叉树,且树中每个节点不包含指向父节点的指针
  4. 情况4,非二叉树,只是普通的多叉树,且树中每个节点不包含指向父节点的指针

情况1,在二叉搜索树中找节点p和q的最低公共祖先


该情况是最简单的形式,根据二叉搜索树的特性,依次从根节点出发遍历,查找第一个值在p和q中间的节点即可。
/*(1)情况1,在二叉搜索树中找节点p和q的最低公共祖先*//*二叉搜索树节点结构*/typedef struct BSTNode {int val;BSTNode *left;BSTNode *right;BSTNode(int val) :val(val), left(NULL), right(NULL) {}};BSTNode *getLastCommonParent1(BSTNode *root, BSTNode *p, BSTNode *q){if (root == NULL)return NULL;BSTNode *ret = root;while (ret != NULL){//如果两个节点p,q的值比根节点ret都大,则最低公共祖先在右子树if (ret->val < p->val && ret->val < q->val){ret = ret->right;}//如果两个节点p,q的值比根节点ret都小,则最低公共祖先在左子树else if (ret->val > p->val && ret->val > q->val) {ret = ret->left;}//如果ret的值在p和q的中间,则ret即是p和q的最低公共祖先else {break;}}//whilereturn ret;}

情况2,非二叉搜索树,只是普通的二叉树,树中每个节点包含指向父节点的指针


此时,所给节点p和q均有一条指向跟节点root的链表。该题目即可转换为两个链表的第一个公共节点。
/*(2)情况2,非二叉搜索树,只是普通的二叉树,树中每个节点包含指向父节点的指针此时,所给节点p和q均有一条指向跟节点root的链表。该题目即可转换为两个链表的第一个公共节点。*//*含有父节点指针的普通二叉树节点结构*/typedef struct TPNode {int val;TPNode *left;TPNode *right;TPNode *parent;TPNode(int val) :val(val), left(NULL), right(NULL), parent(NULL) {}};TPNode *getLastCommonParent2(TPNode *root, TPNode *p, TPNode *q){if (root == NULL)return NULL;int pLen = 0, qLen = 0;TPNode *pTmp = p;while (pTmp != NULL){++pLen;pTmp = pTmp->parent;}TPNode *qTmp = q;while (qTmp != NULL){++qLen;qTmp = qTmp->parent;}pTmp = p;qTmp = q;if (pLen > qLen){int diff = pLen - qLen;while (diff > 0){pTmp = pTmp->parent; --diff;}//while}else {int diff = qLen - pLen;while (diff > 0){qTmp = qTmp->parent; --diff;}}//elsewhile (pTmp != qTmp){pTmp = pTmp->parent;qTmp = qTmp->parent;}return pTmp;}

情况3,非二叉搜索树,只是普通的二叉树,且树中每个节点不包含指向父节点的指针


此时,顺着一条p和q都在同一边的链子,也就是说,如果p和q都在某节点的左边,就到左子树中去查找公共祖先,如果都在右边就去右子树去查找公共祖先。要是p和q不在同一边,那么就表示已经找到第一个公共祖先。
/*(3)情况3,非二叉搜索树,只是普通的二叉树,且树中每个节点不包含指向父节点的指针此时,顺着一条p和q都在同一边的链子,也就是说,如果p和q都在某节点的左边,就到左子树中去查找公共祖先,如果都在右边就去右子树去查找公共祖先。要是p和q不在同一边,那么就表示已经找到第一个公共祖先。*//*不含父节点指针的普通二叉树节点结构*/typedef struct BTNode {int val;BTNode *left;BTNode *right;BTNode(int val) :val(val), left(NULL), right(NULL) {}};bool judge(BTNode *root, BTNode *p){//判断二叉树root中是否含有节点pif (root == NULL)return false;if (root == p)return true;return judge(root->left, p) || judge(root->right, p);}BTNode *getLastCommonParent3(BTNode *root, BTNode *p, BTNode *q){if (root == NULL || !judge(root,p) || !judge(root,q))return NULL;if (root == p || root == q)return root;/*p和q不在root的同一边,说明root即是它们的最低公共祖先*/bool isPOnLeft = judge(root->left, p);bool isQOnLeft = judge(root->left, q);/*如果p和q都在root的左边*/if (isPOnLeft && isQOnLeft){return getLastCommonParent3(root->left, p, q);}//否则如果p和q都在root的右边else if(!isPOnLeft && !isQOnLeft){return getLastCommonParent3(root->right, p, q);}//否则,说明p和q不在同一边,此时便找到两者最低公共祖先else {return root;}}

情况4,非二叉树,只是普通的多叉树,且树中每个节点不包含指向父节点的指针


此时,先求得从根节点到p和q的路径,转换为求链表的最后一个公共子节点。
/*(4)情况4,非二叉树,只是普通的多叉树,且树中每个节点不包含指向父节点的指针此时,先求得从根节点到p和q的路径,转换为求链表的最后一个公共子节点。*//*含有父节点指针的普通二叉树节点结构*/typedef struct TreeNode {int val;TreeNode *left;vector<TreeNode *> m_vChildren;TreeNode(int val) :val(val), m_vChildren(vector<TreeNode*>()) {}};//获取node节点在树root中的路径bool getNodePath(TreeNode *root, TreeNode *node, vector<TreeNode *> &path){if (root == node)return true;path.push_back(root);bool found = false;vector<TreeNode *>::iterator iter = root->m_vChildren.begin();while (!found && iter < root->m_vChildren.end()){found = getNodePath(*iter, node, path);++iter;}//whileif (!found)path.pop_back();return found;}TreeNode *getLastCommonNode(vector<TreeNode *> pV, vector<TreeNode *> qV){if (pV.empty() && qV.empty())return NULL;vector<TreeNode *>::iterator pIter = pV.begin(), qIter = qV.begin();TreeNode *ret = NULL;while (pIter != pV.end() && qIter != qV.end()){if (*pIter == *qIter)ret = *pIter;++pIter;++qIter;}//whilereturn ret;}TreeNode *getLastCommonParent4(TreeNode *root, TreeNode *p, TreeNode *q){if (root == NULL)return NULL;vector<TreeNode *> pV, qV;getNodePath(root, p, pV);getNodePath(root, q, qV);return getLastCommonNode(pV, qV);}







1 0
原创粉丝点击