package com.fanlu.leetcode.binarytree;
// Source : https://leetcode.com/problems/lowest-common-ancestor-of-a-binary-tree/
// Id : 236
// Author : Fanlu Hai
// Date : 2018-04-24
// Other : lowest common ancestor (LCA): The lowest common ancestor is defined between two nodes p and q
// as the lowest node in T that has both p and q as descendants
// (where we allow a node to be a descendant of itself).
// Tips :
import java.util.LinkedList;
import java.util.Queue;
/**
* Definition for a binary tree node.
* public class TreeNode {
* int val;
* TreeNode left;
* TreeNode right;
* TreeNode(int x) { val = x; }
* }
*/
public class LowestCommonAncestorOfABinaryTree {
private TreeNode ans;
// This answer is copied from leetcode submission analysis sample
// 100.00% (20% faster than original) 44.21%
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
this.recurse(root, p, q);
return this.ans;
}
private boolean recurse(TreeNode node, TreeNode p, TreeNode q) {
if (node == null) {
return false;
}
// rec left
// it's very hard for me to write below code even though it's nothing hard.
int left = this.recurse(node.left, p, q) ? 1 : 0;
int right = this.recurse(node.right, p, q) ? 1 : 0;
int mid = (node == p) || (node == q) ? 1 : 0;
// this is better than comparing objects
if (mid + left + right >= 2) {
this.ans = node;
}
return (mid + left + right > 0);
}
//65.83% 40.60%
// this is fast enough to my understanding, but there are more elegant and faster ways to do the same steps
public TreeNode lowestCommonAncestorOriginal(TreeNode root, TreeNode p, TreeNode q) {
if (null == root || root == p || root == q)
return root;
TreeNode left = lowestCommonAncestorOriginal(root.left, p, q);
TreeNode right = lowestCommonAncestorOriginal(root.right, p, q);
if (null != left && null != right) {
return root;
} else if (null == right) {
return left;
} else {
// null == left
return right;
}
//return left == null ? right : right == null ? left : root;
}
/**
* below are some no very successfull attampts
*/
Queue pNodeList = new LinkedList();
Queue qNodeList = new LinkedList();
//! Time Limit Exceeded
public TreeNode lowestCommonAncestorTooSlow(TreeNode root, TreeNode p, TreeNode q) {
TreeNode result = root;
dfsNode(root, p, q, new LinkedList());
while (!pNodeList.isEmpty()) {
TreeNode tmp = pNodeList.poll();
// System.out.println(tmp);
if (tmp != qNodeList.poll()) {
break;
}
result = tmp;
}
return result;
}
public void dfsNode(TreeNode treeNode, TreeNode p, TreeNode q, Queue queue) {
if (null == treeNode)
return;
Queue tmpQueue = new LinkedList();
tmpQueue.addAll(queue);
tmpQueue.add(treeNode);
if (treeNode.val == p.val) {
pNodeList = tmpQueue;
}
if (treeNode.val == q.val) {
qNodeList = tmpQueue;
}
dfsNode(treeNode.left, p, q, tmpQueue);
dfsNode(treeNode.right, p, q, tmpQueue);
}
Queue pList = new LinkedList();
Queue qList = new LinkedList();
// implemented the int version
public int lowestCommonAncestorReturnInt(TreeNode root, TreeNode p, TreeNode q) {
int result = root.val;
dfsValue(root, p.val, q.val, new LinkedList());
while (!pList.isEmpty()) {
int tmp = pList.poll();
// System.out.println(tmp);
if (tmp != qList.poll()) {
break;
}
result = tmp;
}
return result;
}
public void dfsValue(TreeNode treeNode, int p, int q, Queue queue) {
if (null == treeNode)
return;
Queue tmpQueue = new LinkedList();
tmpQueue.addAll(queue);
tmpQueue.add(treeNode.val);
if (treeNode.val == p) {
pList = tmpQueue;
}
if (treeNode.val == q) {
qList = tmpQueue;
}
dfsValue(treeNode.left, p, q, tmpQueue);
dfsValue(treeNode.right, p, q, tmpQueue);
}
public static void main(String[] args) {
TreeNode treeNode1 = new TreeNode(1);
TreeNode treeNode2 = new TreeNode(2);
TreeNode treeNode3 = new TreeNode(3);
TreeNode treeNode4 = new TreeNode(4);
TreeNode treeNode5 = new TreeNode(5);
TreeNode treeNode6 = new TreeNode(6);
TreeNode treeNode7 = new TreeNode(7);
treeNode1.left = treeNode2;
treeNode2.left = treeNode4;
treeNode2.right = treeNode5;
treeNode5.right = treeNode3;
treeNode3.left = treeNode6;
treeNode3.right = treeNode7;
LowestCommonAncestorOfABinaryTree lowestCommonAncestorOfABinaryTree = new LowestCommonAncestorOfABinaryTree();
lowestCommonAncestorOfABinaryTree.dfsValue(treeNode1, 7, 6, new LinkedList());
for (int i : lowestCommonAncestorOfABinaryTree.pList) {
System.out.print(i + "*");
}
System.out.println();
for (int i : lowestCommonAncestorOfABinaryTree.qList) {
System.out.print(i + "-");
}
System.out.println();
System.out.println("result: " + lowestCommonAncestorOfABinaryTree.lowestCommonAncestorReturnInt(treeNode1, treeNode7, treeNode6));
}
}