68-二叉搜索树的最近公共祖先

16 篇文章 0 订阅
7 篇文章 0 订阅

        给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先。百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。

如输入: root = [6,2,8,0,4,7,9,null,null,3,5], p = 2, q = 8;输出: 6 。解释: 节点 2 和节点 8 的最近公共祖先是 6。

        既然给定的是二叉搜索树,则意味着树的左节点的值小于根节点,根节点的值小于右子节点。要求最近公共祖先有两种方式:

        1.对二叉搜索树做两次遍历,分别找到root和p以及root和q的公共节点。定义两个集合path_p,path_q用来保存根节点到p节点和到q节点的路径。再次对path_p、path_q进行遍历,找到两个元素的不相同节点,则该节点的上一个节点即为深度最大的公共节点,也就是公共祖先。实现方法为lowestCommonAncestor。

        2.对二叉搜索树只做一次遍历,定义变量temp对二叉搜索树进行遍历,并将的值.val和p、q节点的值进行大小比较,如果temp的节点值小于p和q的值,则公共祖先肯定在temp的右节点,将temp.right赋值给temp,继续循环;如果大于p和q,则公共祖先在temp的左节点,将temp.left赋值给temp,继续循环;如果是其他情况,则返回temp。实现方法为lowestCommonAncestorNew方法。

package leecodeOff;
/*
 * 68.二叉搜索树的最近公共祖先
 */

import java.util.ArrayList;
import java.util.List;

public class Demo68 {

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
    	path_p = getPath(root,p);
    	path_q = getPath(root,q);
    	int length_p = path_p.size();
    	int length_q = path_q.size();
    	if(length_p == 0 || length_q == 0) {
    		return null;
    	}
    	for(int i=0;i<length_p;i++) {
    		TreeNode node1 = path_p.get(i);
    		TreeNode node2 = path_q.get(i);
    		if(node1 != node2) {
    			return path_p.get(i-1);
    		}
    	}
    	return path_p.get(0);
    	
    }
    List<TreeNode> path_p = new ArrayList<TreeNode>();
    List<TreeNode> path_q = new ArrayList<TreeNode>();
   
    public List<TreeNode>  getPath(TreeNode root,TreeNode target) {
    	List<TreeNode> path = new ArrayList<TreeNode>();
    	while(root!=null) {
    		TreeNode temp = root;
    		path.add(temp);
    		if(target.val < temp.val) {
    			root = temp.left;
    		}else if(target.val > temp.val) {
    			root = temp.right;
    		}else {
    			break;
    		}
    	}
    	path.add(root);
    	return path;
    }
	//这个方法非常好
    public TreeNode lowestCommonAncestorNew(TreeNode root, TreeNode p, TreeNode q) {
    	TreeNode temp = root;
    	while(true) {
    		int val1 = temp.val;
    		int val2 = p.val;
    		int val3 = q.val;
    		if(val2 < val1 && val3< val1) {
    			temp =  temp.left;
    		}else if(val2 > val1 && val3>val1) {
    			temp =  temp.right;
    		}else {
    			break;
    		}
    	}
    	return temp;
    }

    
    public static void main(String args[]) {
    	Demo68 demo = new Demo68();
    	TreeNode node1 = new TreeNode(6);
		 TreeNode node21 = new TreeNode(2);
		 TreeNode node22 = new TreeNode(8);
		 TreeNode node31 = new TreeNode(0);
		 TreeNode node32 = new TreeNode(4);
		 TreeNode node33 = new TreeNode(7);
		 TreeNode node34 = new TreeNode(9);
		 TreeNode node51 = new TreeNode(3);
		 TreeNode node52 = new TreeNode(5);
		 node1.left = node21;
		 node1.right = node22;
		 node21.left = node31;
		 node21.right = node32;
		 node22.left = node33;
		 node22.right = node34;
		 node32.left = node51;
		 node32.right = node52;
   
		 TreeNode node = demo.lowestCommonAncestor(node1, node21, node22);
		 System.out.println(node.val);
    }
    
}

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

sunny_daily

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值