详细的询问:
1、该树是二叉查找树? 最近公共祖先----二叉查找树:(http://www.lintcode.com/problem/lowest-common-ancestor/)
思路:利用左子树特点:左子树 < 根 <= 右,输入节点跟根节点比较,都小于,在左子树,都大约右子树,递归的去遍历;找到当前节点在两个输入大小之间,当前节点就是。
递归和非递归
public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null) { return null; } if (root.val > Math.max(p.val, q.val)) { return lowestCommonAncestor(root.left, p, q); } else if (root.val < Math.min(p.val, q.val)) { return lowestCommonAncestor(root.right, p, q); } else{ return root; } } } 非递归: public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { while(true){ if (root.val > Math.max(p.val, q.val)){ root = root.left; } else if (root.val < Math.min(p.val, q.val)){ root = root.right; } else{ break; } } return root; } }
2、该树有指向父节点的指针
最近公共祖先----普通的树有指向父节点的指针:
思路:转换为求两个链表的第一个公共节点。从叶子节点到根节点都是由一个pparent连起来的链表。
对齐或栈
方法1:计算两个链表长度,len = 长度之差,对齐链表,然后依次遍历比较 /** * Definition of ParentTreeNode: * * class ParentTreeNode { * public ParentTreeNode parent, left, right; * } */ public class Solution { /** * @param root: The root of the tree * @param A, B: Two node in the tree * @return: The lowest common ancestor of A and B */ public ParentTreeNode lowestCommonAncestorII(ParentTreeNode root, ParentTreeNode A, ParentTreeNode B) { int a_L = getL(A); int b_L = getL(B); int diff = a_L - b_L; ParentTreeNode l = A; ParentTreeNode s = B; if(diff < 0){ l = B; s = A; diff = b_L - a_L; } while(diff > 0) { l = l.parent; diff--; } while(l != null && s != null && l != s) { l = l.parent; s = s.parent; } return l; } public int getL(ParentTreeNode node){ int len = 0; ParentTreeNode pnode = node; while(pnode != null) { pnode = pnode.parent; len++; } return len; } } 方法2:将两个链表存入栈或数组,逆序输出比较,直到找到第一个不相等的。
3、最近公共祖先----普通树,没有指针()
1)ab在树里,后序遍历,递归
public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if (root == null) return null; if (root == p || root == q) return root; // Post order traveral TreeNode l = lowestCommonAncestor(root.left, p, q); TreeNode r = lowestCommonAncestor(root.right, p, q); if (l != null && r != null) { return root; } else { return l != null ? l : r; } }
2)可能不在树里
思路: 在二叉树中来搜索p和q,然后从路径中找到最后一个相同的节点即为父节点,我们可以用递归来实现.后序遍历二叉树,得到从根节点到目标节点的“路径”。
方法一、
1)判断改点在不在子树中covers()
2)公共祖先helper()分同边,异边
改方法每次都会重复访问在不在子树,
public class Solution { public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) { if(!covers(root,A) || !covers(root,B)){ return null; } return Helper(root, A, B); } //判断该节点node是否在当前节点root的子树里 public boolean covers(TreeNode root, TreeNode node){ if(root == null) { return false; } if(root == node){ return true;//当前节点即为node } return covers(root.left, node) || covers(root.right, node);//节点在当前节点的左右子树里 } //找公共节点 public TreeNode Helper(TreeNode root, TreeNode A, TreeNode B) { // write your code here if(root == null) { return null; } if (root == A || root == B){ return root; } boolean a_i_L = covers(root.left, A); boolean b_i_L = covers(root.left, B); //不在同一边 if(a_i_L != b_i_L){ return root; } //在通一边 TreeNode child_side = b_i_L ?root.left : root.right; return Helper(child_side, A, B); } }
方法二:构造一个结构类,两种方法。
class ResultType { public boolean a_exist, b_exist; public TreeNode node; ResultType(boolean a, boolean b, TreeNode n) { a_exist = a; b_exist = b; node = n; } } public class Solution { public TreeNode lowestCommonAncestor3(TreeNode root, TreeNode A, TreeNode B) { // write your code here ResultType rt = helper(root, A, B); if (rt.a_exist && rt.b_exist) return rt.node; else return null; } public ResultType helper(TreeNode root, TreeNode A, TreeNode B) { if (root == null) return new ResultType(false, false, null); ResultType left_rt = helper(root.left, A, B); ResultType right_rt = helper(root.right, A, B); boolean a_exist = left_rt.a_exist || right_rt.a_exist || root == A; boolean b_exist = left_rt.b_exist || right_rt.b_exist || root == B; if (root == A || root == B) return new ResultType(a_exist, b_exist, root); if (left_rt.node != null && right_rt.node != null) return new ResultType(a_exist, b_exist, root); if (left_rt.node != null) return new ResultType(a_exist, b_exist, left_rt.node); if (right_rt.node != null) return new ResultType(a_exist, b_exist, right_rt.node); return new ResultType(a_exist, b_exist, null); } }