LeetCode_Lowest Common Ancestor

来源:互联网 发布:电脑端口怎么打开 编辑:程序博客网 时间:2024/06/06 05:01

题目:给出一颗二叉树中的节点n1和n2,要求找出两个节点的深度最低的祖先节点。节点的定义方式如下:

struct TreeNode{    int val;    TreeNode *left;    TreeNode *right;    TreeNode(int val):val(val),left(NULL),right(NULL){};}; 
这道题虽然不是OJ中的,但是觉得是一道很好的题目,同时与OJ中的二叉树相关题目相比还算挺有难度的。

何海涛在他的博客中给出了一个自顶之下构造两个单链表来求解这个问题的解法,建议大家先看一下。

LeetCode上有人给出了Lowest Common Ancestor of a Binary Tree Part I一个自底向上的解法。

英文描述如下:

A Bottom-up Approach (Worst case O(n) ):
Using a bottom-up approach, we can improve over the top-down approach by avoiding traversing the same nodes over and over again.

We traverse from the bottom, and once we reach a node which matches one of the two nodes, we pass it up to its parent. The parent would then test its left and right subtree if each contain one of the two nodes. If yes, then the parent must be the LCA and we pass its parent up to the root. If not, we pass the lower node which contains either one of the two nodes (if the left or right subtree contains either p or q), or NULL (if both the left and right subtree does not contain either p or q) up.

个人翻译一下:自底向上的遍历二叉树(就是深度优先遍历),一旦找到了两个节点其中的一个,就将这个几点返回给上一层,上一层节点通过判断其左右子树中是否恰好包含n1和n2两个节点,如果是这样的话,对应的上一层节点肯定是所求的LCA;若果不是的话,将包括两个节点中任意一个的较低的节点返回给上一层,否则返回NULL。

其代码如下:

class Solution{public:    TreeNode *LowestCommonAncestor(TreeNode *root,TreeNode *n1,TreeNode *n2){        //如果当前根结点为空返回NULL        if (root==NULL){            return NULL;        }        //若当前找到n1或者n2其中一个,则直接返回        if(root==n1||root==n2){            return root;        }        //分别从左右子树中查找n1和n2        TreeNode *left=LowestCommonAncestor(root->left,n1,n2);        TreeNode *right=LowestCommonAncestor(root->right,n1,n2);        //若正好在分别在左右子树中找到n1和n2则说明当前节点就是要找的解        if (left&&right){            return root;        }        //存在三种情况是的函数在此处返回        //1.第一次在左或右子树中找到n1、n2中的某个节点        //2.从在当前节点的左右子树中已经查找到要找的解        //3.以当前节点为根的子树根本就不存在n1和n2        return left?left:right;    }};

注释部分是我自己加的。只看代码有点难想明白,画个图自己走一下就明白了,这里自己写了一个测试用例程序中的根据字符串生成二叉树的代码:

void preOrderPrintTree(TreeNode * root){    if (root==NULL)  {        cout<<"#"<<" ";        return;    }    cout<<root->val<<" ";    preOrderPrintTree(root->left);    preOrderPrintTree(root->right);}void FindNode(TreeNode *root ,int val ,TreeNode *&pf){    if (root==NULL){        return;    }    if (root->val==val){        pf=root;        return;    }    FindNode(root->left,val,pf);    FindNode(root->right,val,pf);}int _tmain(int argc, _TCHAR* argv[]){    string str="{1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16}";    TreeNode *root=StringToBinaryTree(str);    cout<<"PreOrder Travellsor:"<<endl;    preOrderPrintTree(root);    cout<<endl;    TreeNode *n1=NULL;    FindNode(root,16,n1);    TreeNode *n2=NULL;    FindNode(root,8,n2);    Solution ss;    TreeNode *CommonAncester = ss.LowestCommonAncestor(root,n1,n2);    cout<<"8 and 11 Lowest common Ancestor:"<<CommonAncester->val<<endl;return 0;}

程序运行结果如下


0 0