1.当树为搜索二叉树时候。
a. 我们可以根据节点值的大小递归判断。如果根节点大于给定的两个节点值的话,我们就在根节点的左子树里找,如果根节点的值小于给定的两个节点值的话,在根节点的右子树里边找。如果根节点的值在给定的两个节点值中间的话,说明找到了。
b. Java代码:
public class Main {
/*当树为二叉树的时候,当二叉树是搜索二叉树的时候,假设两个节点都存在二叉树中*/
public static TreeNode lowestCommanNode(TreeNode root, TreeNode node1, TreeNode node2) {
if(root == null || node1 == null || node2 == null){
System.err.println("root == null || node1 == null || node2 == null");
//为了能够打印出值,我们对于异常输入,返回-1
return new TreeNode(-1, null, null);
}
return SearchLowestCommanNode(root, node1, node2);
}
public static TreeNode SearchLowestCommanNode(TreeNode root, TreeNode node1, TreeNode node2) {
if(root.val>node1.val&&root.val<node2.val||root.val<node1.val&&root.val>node2.val)return root;
else if(root.val<node1.val&&root.val<node2.val)return SearchLowestCommanNode(root.right, node1, node2);
else if(root.val>node1.val&&root.val>node2.val)return SearchLowestCommanNode(root.left, node1, node2);
return null;
}
public static void main(String[] args) {
TreeNode node6 = new TreeNode(12, null, null);
TreeNode node5 = new TreeNode(10, null, null);
TreeNode node4 = new TreeNode(11, node5, node6);
TreeNode node3 = new TreeNode(8, null, null);
TreeNode node2 = new TreeNode(6, null, null);
TreeNode node1 = new TreeNode(7, node2, node3);
TreeNode node = new TreeNode(9, node1, node4);
System.out.println(lowestCommanNode(node, node3, node4).val);
}
}
2. 当树为普通的带有指向父指针的树。
a. 因为有父指针的存在,所有就相当于两个链表的第一个公共节点。(剑指offer52)
b. Java代码:
public class Main {
/*当树为普通的树的时候,相当于两个单链表的第一公共节点,假设两个节点存在于树中*/
public static Tree lowestCommanNode(Tree node1, Tree node2) {
if(node1 == null || node2 == null){
System.err.println("root == null || node1 == null || node2 == null");
return new Tree(-1);
}
Tree current1 = node1;
Tree current2 = node2;
int nodeToRoot1 = NodeToRootLength(current1);
int nodeToRoot2 = NodeToRootLength(current2);
//让长的先走。
if(nodeToRoot1>nodeToRoot2){
int len = nodeToRoot1 - nodeToRoot2;
while(len>0){
current1 = current1.parent;
}
}else {
int len = nodeToRoot2 - nodeToRoot1;
while(len>0){
current2 = current2.parent;
}
}
//判断接下的相等的第一个节点
while(current1 != null && current2 != null){
if(current1 == current2){
return current1;
}else {
current1 = current1.parent;
current2 = current2.parent;
}
}
return null;
}
public static int NodeToRootLength(Tree node) {
Tree current = node;
int len = 0;
while(current != null){
current = current.parent;
len++;
}
return len;
}
public static void main(String[] args) {
Tree node6 = new Tree(12);
Tree node5 = new Tree(10);
Tree node4 = new Tree(11);
Tree node3 = new Tree(8);
Tree node2 = new Tree(6);
Tree node1 = new Tree(7);
Tree node = new Tree(9);
node.left = node1;
node.right = node2;
node.parent = null;
node1.left = node3;
node1.right = node4;
node1.parent = node;
node2.left = node5;
node2.right = node6;
node2.parent = node;
node3.parent = node1;
node4.parent = node1;
node5.parent = node2;
node6.parent = node2;
System.out.println(lowestCommanNode(node5, node6).val);
}
}
3.当树为普通的树的时候。没有指向父节点的指针。
a. 没有指向父节点的指针的时候,我们只能通过更节点进行往下寻找。我们可以首先把从根节点到所给节点的两个路径找出来并存起来,最后找两个路径中的最后一个公共节点。
b. Java代码:
public class Main {
/*当树为普通的树,并且没有指向父节点的指针*/
public static TreeNode lowestCommanNode(TreeNode root, TreeNode node1, TreeNode node2) {
//异常处理
if(root == null || node1 == null || node2 == null){
System.err.println("root == null || node1 == null || node2 == null");
return new TreeNode(-1, null, null);
}
//创建存放路径的list
ArrayList<ArrayList<TreeNode>> res = new ArrayList<>();
//搜索路径
findPath(root, node1, node2, res, new ArrayList<>());
//如果res中的路径少于两个的话,说明至少有一个节点不在树中
if(res.size() < 2){
System.err.println("There is only a node in the tree!!! ");
return new TreeNode(-1, null, null);
}
//找到最后一个公共节点
int i = 0;
TreeNode result = new TreeNode(0, null, null);
while(i < Math.min(res.get(0).size(), res.get(1).size())&&res.get(0).get(i) == res.get(1).get(i)){
result = res.get(0).get(i);
i++;
}
return result;
}
public static void findPath(TreeNode root, TreeNode node1, TreeNode node2, ArrayList<ArrayList<TreeNode>> res, ArrayList<TreeNode> list) {
//根据先序遍历搜索路径
list.add(root);
if(root == node1||root == node2){
res.add(new ArrayList<>(list));
//如果res的长度为2,两个节点都找到了
if(res.size() == 2)return;
}
if(root.left != null)findPath(root.left, node1, node2, res, list);
if(root.right != null)findPath(root.right, node1, node2, res, list);
list.remove(list.size()-1);
}
public static void main(String[] args) {
TreeNode node7 = new TreeNode(13, null, null);
TreeNode node6 = new TreeNode(12, null, null);
TreeNode node5 = new TreeNode(10, null, null);
TreeNode node4 = new TreeNode(11, node5, node6);
TreeNode node3 = new TreeNode(8, null, null);
TreeNode node2 = new TreeNode(6, null, null);
TreeNode node1 = new TreeNode(7, node3, node4);
TreeNode node = new TreeNode(9, node1, node2);
System.out.println(lowestCommanNode(node, node6, node7).val);
}
}