【牛客 - 剑指offer】JZ68 二叉搜索树的最近公共祖先 两种方案(递归、非递归) Java实现


剑指offer题解汇总 Java实现

https://blog.csdn.net/guliguliguliguli/article/details/126089434

本题链接

知识分类篇 - 树 - JZ68 二叉搜索树的最近公共祖先

题目

在这里插入图片描述

思路 & 代码

方案一 非递归

题目所给的二叉树是二叉搜索树,即比根节点的值小的点均在根节点的左边,比根节点的值大的点,均在根节点的右边

  1. 依据这个性质,用arrayList记录下找到两个指定节点的路径

  2. 最后,比较两个arrayList,返回它们的路径中最后一个相同的数,就是它们的最近公共祖先

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param root TreeNode类
     * @param p    int整型
     * @param q    int整型
     * @return int整型
     */
    public int lowestCommonAncestor(TreeNode root, int p, int q) {

        // write code here
        ArrayList<Integer> p1 = findPath(root, p);
        ArrayList<Integer> p2 = findPath(root, q);

        int res = 0;
        for (int i = 0; i < p1.size() && i < p2.size(); i++) {
            int p1_value = p1.get(i);
            int p2_value = p2.get(i);
            if (p1_value == p2_value) {
                res = p1_value;
            } else {
                break;
            }
        }
        return res;

    }


    public ArrayList<Integer> findPath(TreeNode node, int target) {
        ArrayList<Integer> list = new ArrayList<>();
        while (node.val != target) {
            list.add(node.val);
            if (target > node.val) {
                node = node.right;
            } else {
                node = node.left;
            }
        }
        list.add(target);
        return list;
    }
}

方案二 递归

递归思想

递归是一个过程或函数在其定义或说明中有直接或间接调用自身的一种方法,它通常把一个大型复杂的问题层层转化为一个与原问题相似的规模较小的问题来求解。因为递归过程,最重要的就是查看能不能将原本的问题分解为更小的子问题,这是使用递归的关键。

而二叉树的递归,则是将某个节点的左子树、右子树看成一颗完整的树,那么对于子树的访问或者操作就是对于原树的访问或者操作的子问题,因此可以自我调用函数,不断进入子树。

思路

  1. 判断传入的根节点,是否为空,如果为空,则不存在找两个节点最近公共祖先的问题,返回空即可

  2. 如果两个节点中,其中一个结点的值大于根节点的值,另一个结点的值,小于根节点的值,那么根节点就是这两个节点的最近公共祖先。

    • 特殊情况,其中某一个节点的值等于根节点的值,且题目中明确表示p和q是不同的节点,那么根节点也是这两个节点的公共节点。
  3. 如果两个节点中,两个节点的值都小于根节点的值,那么调用方法自身,其中的TreeNode类型的参数赋值为root.left,即,两个节点的公共祖先一定在这棵二叉搜索树的左子树上

  4. 如果两个节点中,两个节点的值都大于根节点的值,那么调用方法自身,其中的TreeNode类型的参数赋值为root.righth,即,两个节点的公共祖先一定在这棵二叉搜索树的右子树上

import java.util.*;

/*
 * public class TreeNode {
 *   int val = 0;
 *   TreeNode left = null;
 *   TreeNode right = null;
 *   public TreeNode(int val) {
 *     this.val = val;
 *   }
 * }
 */

public class Solution {
    /**
     * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可
     *
     * @param root TreeNode类
     * @param p    int整型
     * @param q    int整型
     * @return int整型
     */
    public int lowestCommonAncestor(TreeNode root, int p, int q) {
        
        if (root==null){
            return -1;
        }
        if ((p >= root.val && q <= root.val) || (p <= root.val && q >= root.val)) {
            return root.val;
        }
        if (p < root.val && q < root.val) {
            return lowestCommonAncestor(root.left, p, q);
        }
        //if (p > root.val && q > root.val) {
        return lowestCommonAncestor(root.right, p, q);

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值