算法学习之树中两个节点的最低公共祖先

题目:输入两个树节点,求它们的最低公共祖先。

普通的树:

1、我们使用两个LinkedList依次记录从根节点到两个给定节点的路径

2、得到路径后,我们对两个路径进行比较,最后一个相等的节点即为所求(添加与取得顺序相反,所以最后一个为最低公共节点)

  public TreeNode getLastCommonParent(TreeNode root, TreeNode p1, TreeNode p2) {
        if (root == null || p1 == null || p2 == null) return null;
        LinkedList<TreeNode> path1 = new LinkedList<>();
        LinkedList<TreeNode> path2 = new LinkedList<>();
        LinkedList<TreeNode> tem = new LinkedList<>();
        getNodePath(root, p1, tem, path1);
        getNodePath(root, p2, tem, path2);

        if (path1.size() <= 0 || path2.size() <= 0) return null;
        return getCommon(path1, path2);
    }
    // 比较两个path,得到最后一个相同节点,即我们的目标值
    private TreeNode getCommon(LinkedList<TreeNode> path1, LinkedList<TreeNode> path2) {
        TreeNode temNode = null;
        for (int i = 0; i < path1.size(); i++) {
            if (path1.get(i) != path2.get(i)) {
                break;
            }
            temNode = path1.get(i);
        }
        return temNode;

    }
    // 获取
    private void getNodePath(TreeNode root, TreeNode targeNode, LinkedList<TreeNode> tem, LinkedList<TreeNode> path) {
        if (root == targeNode) {
            return;
        }
        tem.add(root);
        List<TreeNode> children = root.children; // 获取左右两个子节点,可能只存在一个,或者0个
        for (TreeNode node : children) { 
            if (node == targeNode) {
                path.addAll(tem);
                break;
            }
            getNodePath(node, targeNode, tem, path);
        }
        tem.removeLast(); // 避免重复添加,删除掉(因为递归的性质,到达底层时,回溯时依次删除)
    }
public class TreeNode {

    public List<TreeNode> children = new ArrayList<>();
    int val;

    TreeNode(int x) {
        val = x;
    }
}
        // 测试数据
        val n1 = TreeNode(1)
        val n2 = TreeNode(2)
        val n3 = TreeNode(3)
        val n4 = TreeNode(4)
        val n5 = TreeNode(5)
        val n6 = TreeNode(6)
        val n7 = TreeNode(7)
        val n8 = TreeNode(8)
        val n9 = TreeNode(9)
        val n10 = TreeNode(10)

        n1.children.add(n2)
        n1.children.add(n3)
        n2.children.add(n4)
        n4.children.add(n6)
        n4.children.add(n7)
        n3.children.add(n5)
        n5.children.add(n8)
        n5.children.add(n9)
        n5.children.add(n10)

        

 

时间复杂度:O(n)

空间复杂度:O(logn)

其实还有另外的情况:如该树为普通二叉树

    /**
     * 递归,找到两个目标节点
      * @param root
     * @param left1
     * @param right1
     * @return
     */
    public TreeNode getLastCommonParent2(TreeNode root,TreeNode left1,TreeNode right1){

        if(root==null||root==left1||root==right1) {
            return root;
        }
        // 递归是一个大过程,回溯时,左子树的右小枝也被算作大枝中的左枝
        TreeNode left = getLastCommonParent2(root.left,left1,right1);
        TreeNode right = getLastCommonParent2(root.right,left1,right1);
        // 左节点为null说明根节点在右子树中或不存在,右节点为null说明根节点在左子树中或不存在,两个都不为null说明root就为目标值
        return left==null?right:right==null?left:root;
        // 等同于
//        if(left==null) {
//            return right;
//        }else {
//            if(right==null) {
//                return left;
//            }else {
//                return root;
//            }
//        }
    }

 

二叉搜索树:

若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。利用此特性遍历递归即可。

public TreeNode getLowestCommonParentBST(TreeNode root,TreeNode node1,TreeNode node2) {
    while(true) {
        if(root==null)
            return root;
        if(root.val<node1.val && root.val<node2.val)
            root=root.right;
        else if(root.val>node1.val && root.val>node2.val)
            root=root.left;
        else
            return root;
    }
}

 

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值