面试题之树中两个节点的最低公共祖先节点

1.树为二叉搜索树,二叉搜索树特点:值:右>根>左

①思路

从根节点开始遍历

a:若该节点值比所给两个节点均大,则公共祖先节点必在其左子树上,遍历其左子树。

b:若该节点值比所给两个节点均小,则公共祖先节点必在其右子树上,遍历其右子树。

c:直到找到一个节点,位于两节点的中间。

Given a binary search tree(BST),find the lowest common ancestor(LCA) of two given nodes in the BST.

According to the definition of LCA on Wikipedia:"The lowest common ancestor is defined between two nodes v and w as the lowest node in T that has both v and w as descendants (where we allow a node to be a descendant of itself)."


For example, the lowest common ancestor (LCA) of nodes 2 and 8 is 6.Another example is LCA of nodes 2 and 4 is 2,since a node can be a descendant of itself according to the LCA definition.

②代码

public class BanarySearchTreeMain {

	public static void main(String[] args) {
		// TODO Auto-generated method stub
		TreeNode root = initTree();
		TreeNode result = lowestCommonAncestor(root, new TreeNode(2), new TreeNode(4));
		System.out.println(result.val);
	}
	/*
	 * 初始化二叉搜索树,其特点:右>根>左;
	 */
	private static TreeNode initTree(){
		TreeNode root = new TreeNode(6);
		TreeNode node0 = new TreeNode(0);
		TreeNode node2 = new TreeNode(2);
		TreeNode node3 = new TreeNode(3);
		TreeNode node4 = new TreeNode(4);
		TreeNode node5 = new TreeNode(5);
		TreeNode node7 = new TreeNode(7);
		TreeNode node8 = new TreeNode(8);
		TreeNode node9 = new TreeNode(9);
		root.left = node2;
		root.right = node8;
		node2.left = node0;
		node2.right = node4;
		node8.left = node7;
		node8.right = node9;
		node4.left = node3;
		node4.right = node5;
		
		return root;
	}
	/*
	 * 二叉搜索树最低公共父节点
	 */
	private static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
		if(root==null||root==p||root==q) {
			return root;
		}
		if(root.val>p.val&&root.val>q.val) {
			return lowestCommonAncestor(root.left, p, q);
		}
		if(root.val<p.val&&root.val<q.val) {
			return lowestCommonAncestor(root.right, p, q);
		}else {
			return root;
		}
	}
	
	
}

class TreeNode {
	int val;
	TreeNode left;
	TreeNode right;
	TreeNode(int x) {
		val = x;
	}

}

2.树为普通二叉树

①思路

a:遍历左子树,若与两节点中某值相等或左右均不为null,则返回根节点,否则,继续遍历;

b:遍历右子树,若与两节点中某值相等或左右均不为null,则返回根节点,否则,继续遍历;

c:返回节点;

For example,the lowest common ancestor (LCA) of nodes 5 and 1 is 3.Another example is LCA of nodes 5 and 4 is 5, since a node can be a descendant of itself according to the LCA definition.

②代码

public class CommonTreeMain {

	public static void main(String[] args) {
		TreeNode root = initTree();
		TreeNode result = lowestCommonAncestor(root, new TreeNode(5), new TreeNode(4));
		
		System.out.println(result.val);
	}
	
	private static TreeNode initTree(){
		TreeNode root = new TreeNode(3);
		TreeNode node0 = new TreeNode(0);
		TreeNode node1 = new TreeNode(1);
		TreeNode node2 = new TreeNode(2);
		TreeNode node4 = new TreeNode(4);
		TreeNode node5 = new TreeNode(5);
		TreeNode node6 = new TreeNode(6);
		TreeNode node7 = new TreeNode(7);
		TreeNode node8 = new TreeNode(8);
		root.left = node5;
		root.right = node1;
		node5.left = node6; 
		node5.right = node2; 
		node1.left = node0;
		node1.right = node8;
		node2.left = node7;
		node2.right = node4;
		return root;
	}
	
	/*
	 * 查找最低公共祖先节点
	 */
    private static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {  
        if(root==null||root.val==p.val||root.val==q.val)  
            return root;  
        TreeNode left = lowestCommonAncestor(root.left,p,q);  
        TreeNode right = lowestCommonAncestor(root.right,p,q);  
        if (left == null)   
            return right;  
        if (right == null)   
            return left;  
        return root;  
    }  
}

③迭代算法:

需要我们保存下由root根节点到p和q节点的路径,并且将路径存入list中,则问题转化为求两个list集合的最后一个共同元素。

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {    
            if(root==null || p==null || q==null)   
                return null;  
            List<TreeNode> pathp = new ArrayList<>();    
            List<TreeNode> pathq = new ArrayList<>();    
            pathp.add(root);    
            pathq.add(root);    
                
            getPath(root, p, pathp);    
            getPath(root, q, pathq);    
                
            TreeNode lca = null;    
            for(int i=0; i<pathp.size() && i<pathq.size(); i++) {    
                if(pathp.get(i) == pathq.get(i))   
                    lca = pathp.get(i);    
                else   
                    break;    
            }    
            return lca;    
        }    
            
        private boolean getPath(TreeNode root, TreeNode n, List<TreeNode> path) {    
            if(root==n)     
                return true;    
              
            if(root.left!=null) {    
                path.add(root.left);    
                if(getPath(root.left, n, path))  
                    return true;    
                path.remove(path.size()-1);    
            }    
                
            if(root.right!=null) {    
                path.add(root.right);    
                if(getPath(root.right, n, path))   
                    return true;    
                path.remove(path.size()-1);    
            }    
            return false;    
        }  
转载: http://blog.csdn.net/qq_25827845/article/details/74612786


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值