二叉树两个节点求最近的公共祖先节点java代码实现

来源:互联网 发布:ubuntu 命令行界面 编辑:程序博客网 时间:2024/05/18 01:21

求二叉树中任意两个节点的最近公共祖先也称为LCA问题(Lowest Common Ancestor)。

求解LCA问题,应该首先考虑二叉树的特性和二叉树结点的结构,先看二叉树是否是搜索二叉树,若为普通二叉树则要考虑二叉树结点是否包含指向父结点的指针。

一、二叉搜索树

二叉搜索树是排序过的 ,位于左子树的结点都比父结点小,位于右子树的结点都比父结点大。

求解思路:

从树根开始,该节点的值为t,如果t大于t1和t2,说明t1和t2都位于t的左侧,所以它们的共同祖先必定在t的左子树中,从t.left开始搜索;
如果t小于t1和t2,说明t1和t2都位于t的右侧,那么从t.right开始搜索;
如果t1

public int query(Node t1, Node t2, Node t) {      int left = t1.value;      int right = t2.value;      Node parent = null;      if (left > right) {          int temp = left;          left = right;          right = temp;      }      while (true) {          if (t.value < left) {              parent = t;              t = t.right;          } else if (t.value > right) {              parent = t;              t = t.left;          } else if (t.value == left || t.value == right) {              return parent.value;          } else {              return t.value;          }      }  }

其中,parent用于处理t1是t2的祖先(或t2是t1的祖先)的情况。

二、普通二叉树(包含指向父结点的指针)

结点包含指向父结点的指针,这个问题可以转换成求两个链表的第一个公共结点,假设树结点中指向父结点的指针是parent,树的每一个叶结点开始都由一个指针parent串起来的链表,每个链表的尾结点就是树的根结点。那么输入的这两个结点位于链表上,它们的最低公共祖先结点刚好是这两个链表的第一个公共结点。

public int GetHigh(TreeNode root,TreeNode node){    int len=0;    while(node!=null){        len++;        node=node.parent;    }    return len;}public TreeNode GetLastCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2)  {      if (root == null || node1 == null || node2 == null)          return null;      int len1 = GetHigh(root, node1);//一个链表的高度      int len2 = GetHigh(root, node2);//另一个链表的高度      //寻找两个链表的第一个交点      if(len1 != len2)      {          if (len1 < len2) {            for(int i=0;i<len2-len1;i++){                node2=node2.parent;            }        }        else {            for(int i=0;i<len1-len2;i++){                node1=node1.parent;            }        }    }      while (node1 && node2 && node1 != node2)      {          node1 = node1.parent;          node2 = node2.parent;      }      if (node1 == node2)          return node1;      else          return null;  } 

三、普通二叉树(不包含指向父结点的指针)

求解思路:
在二叉树根结点的左子树和右子树中分别找输入的两个结点,如果两个结点都在左子树,遍历当前结点的左子树,如果两个结点都在右子树,遍历当前结点的右子树,直到一个在当前结点的左子树,一个在当前结点的右子树,返回当前结点就是最低的公共祖先结点。

public boolean IsNodeInTree(TreeNode pRoot, TreeNode pNode)  {      if (pRoot == null || pNode == null)          return false;      if (pNode == pRoot)          return true;      if (IsNodeInTree(pRoot.left, pNode) || IsNodeInTree(pRoot.right, pNode))          return true;      return false;  }  public TreeNode GetCommonAncestor(TreeNode pRoot, TreeNode node1, TreeNode node2)  {      if (pRoot == null)          return null;      if (node1 == pRoot && IsNodeInTree(pRoot, node2) || node2 == pRoot && IsNodeInTree(pRoot, node1))          return pRoot;      boolean node1left = IsNodeInTree(pRoot.left, node1);      boolean node1right = IsNodeInTree(pRoot.right, node1);      boolean node2left = IsNodeInTree(pRoot.left, node2);      boolean node2right = IsNodeInTree(pRoot.right, node2);      if (node1left && node2right || node1right && node2left)          return pRoot;      if (node1left && node2left)          return GetCommonAncestor(pRoot.left, node1, node2);      if (node1right && node2right)          return GetCommonAncestor(pRoot.right, node1, node2);      return null;  } 
阅读全文
0 0
原创粉丝点击