9.树中两个节点的最低公共祖先

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);
	}
}


  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值