leetcode 美團筆試也考到了就是要找二叉樹兩個節點的第一個共同的祖先。對於樹,沒有規定,不一定是一顆二叉查找樹。
第一種情況:首先 如果這個樹是一個二叉樹的,並且是一顆二叉查找樹的話
由於二叉查找樹的左子樹節點比父節點小,右子樹節點比父節點大,則輸入兩個節點,只用從根節點開始比較,如果,如果當前節點比這兩個節點都大,則最低的公共父節點一定在左子樹中,那么遍歷左子樹節點。如果當前節點比兩個節點小,那么遍歷右子節點。這樣,找到的第一個值在二者之間的節點就是公共的最低的祖先。
代碼如下:(在leetcode的ac代碼)
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode node1, TreeNode node2) { if(node1.val>node2.val){ TreeNode temp = node1; node1 = node2; node2 =temp; } if(root==null||root==node1||root==node2) return root; if(node1.val<root.val&&node2.val>root.val) return root; else if(node1.val<root.val&&node2.val<root.val) return lowestCommonAncestor(root.left,node1, node2); else return lowestCommonAncestor(root.right,node1, node2); } }
第二種情況:如果只是一般的二叉樹,不是搜索樹的話 可以用遞歸的方法:方法思路如下:收下看root是否為公共祖先,不是的話,則遞歸到左右節點(可能效率不怎么好)
/** * Definition for a binary tree node. * public class TreeNode { * int val; * TreeNode left; * TreeNode right; * TreeNode(int x) { val = x; } * } */ public class Solution { public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) { if(root==null||root==p||root==q) return root; TreeNode left = lowestCommonAncestor(root.left,p,q); TreeNode right =lowestCommonAncestor(root.right,p,q); if(left!=null&&right!=null) return root; return left!=null?left:right; } }
第三種 如果這個就是一個一般的樹 亦不一定是二叉樹。如何處理?思路就是找出這兩個節點的路徑,並存在鏈表中,則這兩個鏈表的交點就是最低公共祖先
實現如下:
/*-------------------第二種情況--------------------------------------------*/ //如果這個樹只是一個一般的樹 也不一定是是二叉樹。這里當做二叉樹來處理吧。不是二叉樹的情況也一樣的方法。 public TreeNode fin_nearances3(TreeNode node1,TreeNode node2,TreeNode root){ if(root==null||node1==root||node2==root) return root; List<TreeNode> path1 = new ArrayList<>(); List<TreeNode> path2 = new ArrayList<>(); findpath(root, node1, path1); findpath(root,node2,path2); return findlastcommonNode(path1, path2); } //找出節點P的路徑 存在path中,如果不存在的話就返回false public boolean findpath(TreeNode root,TreeNode p,List<TreeNode> res){ if(root==p) { res.add(root); return true; } res.add(root); boolean found = false; found = findpath(root.left, p, res); found = findpath(root.right, p, res); if(!found) res.remove(res.size()-1); return found; } //找出兩個path的最后一個公共的節點 public TreeNode findlastcommonNode(List<TreeNode> path1,List<TreeNode> path2){ TreeNode res = null; int i=0; while(i<path1.size()&&i<path2.size()){ if(path1.get(i)==path2.get(i)) res = path1.get(i); i++; } return res; }
//如果只是普通的樹 不一定是二叉樹 但是節點中有指向父節點的指針。這樣將問題轉化為兩個鏈表的第一個交點。
貼一下此博主的解法:
http://blog.csdn.net/xyzbaihaiping/article/details/52122885