每日一题算法:2020年9月27日 [ 二叉搜索树的最近公共祖先]lowestCommonAncestor

2020年9月27日 二叉搜索树的最近公共祖先lowestCommonAncestor

在这里插入图片描述

/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     int val;
 *     TreeNode left;
 *     TreeNode right;
 *     TreeNode(int x) { val = x; }
 * }
 */

class Solution {
    TreeNode res=null;
    int a,b;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

        a=p.val;
        b=q.val;

        test(root);

        return res;

    }

    public int test(TreeNode root){

        int num=0;
        if (root.left!=null) {
            num+=test(root.left);

        }
        if (root.right!=null){
            num+=test(root.right);
        }

        if (root.val==a||root.val==b)
            num++;

        if (num==1)
            return 1;
        if (num==2){
            res=root;
        }
        return 0;

    }
}

解题思路:

今天因为又是简单题,而且看题目就知道又是递归,所以尝试了一下新功能模拟面试,从看题目到思考再加上写代码的过程全加起来只用了不到总时间的一半。

现在回忆一下,当时的思路是这样的,首先,二叉树的节点的值都是不一样的,所以,传入的两个节点实际上有用的就是他们的值而已。

接下来的问题是,如何判断一个节点是否是最近的公共祖先,我的想法是使用递归,设定一个规则使第一个符合规则的就是我们需要的公共祖先,然后我们就跳出递归,但是我没想到有什么方法可以直接跳出递归的流程的,所以,我当符合条件后就破坏条件,使后面出现的符合要求的公共祖先不符合要求,这样得到的就是最接近的公共祖先了。

那么这个规则如何设计?我是这么实现的,判断这两个节点是否在这当前节点的两边,

如果两边都没有,表示当前节点的后代节点中没有要找的节点。

如果只在一边,那么说明这一边的子节点必定比当前节点接近。或者是另一边不存在目标节点,那么最佳公共祖先必定是该节点的一个祖先节点。

如果分配在两边,那么当前节点就是最近的祖先了。

如果分配在一遍,并且当前值也是,那么也可以确定是当前节点。

代码设计:

判断一个节点是否是最进公共祖先,先递归他的两个子节点,确定他们是否是最近公共祖先。

先递归再判断可以保证我们找到的第一个符合条件的就是最近的公共祖先。

如果当前节点左右子树中都没有目标节点,并且当前节点也不是目标节点,返回0,表示这个节点的子树中没有目标节点。

如果当前节点左右子树中都没有目标节点,并且当前节点就是目标节点。或者当前节点的子树中存在目标节点。返回1,表示当前节点中存在一个目标节点。

这样我们递归一个节点得到的两个值就是左右节点中目标节点的个数,当个数等于2时,表示当前节点就是最近祖先节点。

代码实现:

在这里插入图片描述
在这里插入图片描述

TreeNode res=null;
int a,b;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {

    a=p.val;
    b=q.val;

    test(root);

    return res;

}

public int test(TreeNode root){


    int num=0;
    if (root.left!=null) {
        num+=test(root.left);

    }
    if (root.right!=null){
        num+=test(root.right);
    }

    if (root.val==a||root.val==b)
        num++;

    if (num==1)
        return 1;
    if (num==2){
        res=root;
    }
    return 2;

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值