手撕真题-计算二叉树中两个节点之间的距离

思路

求解代码

java 复制代码
 public class TreeDistance {

        /**
         * 计算两个节点在二叉树中的距离
         *
         * @param root 二叉树的根节点
         * @param p    第一个节点
         * @param q    第二个节点
         * @return 两个节点之间的距离
         */
        public int distanceBetweenNodes(TreeNode root, TreeNode p, TreeNode q) {
            // 首先找到两个节点的最近公共祖先(LCA)
            TreeNode lca = findLCA(root, p, q);
            // 计算节点p到LCA的深度
            int depthP = findDepth(lca, p);
            // 计算节点q到LCA的深度
            int depthQ = findDepth(lca, q);
            // 两个节点之间的距离等于它们到LCA的深度之和
            return depthP + depthQ;
        }

        /**
         * 查找二叉树中两个节点的最近公共祖先(LCA)
         *
         * @param root 二叉树的根节点
         * @param p    第一个目标节点
         * @param q    第二个目标节点
         * @return 最近公共祖先节点,如果其中一个节点是根节点,则返回该节点;如果两个节点分别在左右子树中,则返回它们的根节点
         */
        private TreeNode findLCA(TreeNode root, TreeNode p, TreeNode q) {
            // 如果根节点为空,或者根节点是p或q中的一个,直接返回根节点
            if (root == null || root == p || root == q) {
                return root;
            }
            // 递归查找左子树中的LCA
            TreeNode left = findLCA(root.left, p, q);
            // 递归查找右子树中的LCA
            TreeNode right = findLCA(root.right, p, q);
            // 如果左右子树都找到了非空节点,说明p和q分别在左右子树中,当前节点就是LCA
            if (left != null && right != null) {
                return root;
            }
            // 如果左子树找到非空节点,则返回左子树的结果,否则返回右子树的结果
            return left != null ? left : right;
        }


        /**
         * 查找目标节点在给定祖先节点下的深度
         *
         * @param ancestor 起始祖先节点
         * @param target   目标节点
         * @return 目标节点相对于祖先节点的深度,如果未找到则返回-1
         */
        private int findDepth(TreeNode ancestor, TreeNode target) {
            // 如果祖先节点为空,说明无法找到目标节点,返回-1
            if (ancestor == null) {
                return -1;
            }
            // 如果当前节点就是目标节点,深度为0
            if (ancestor == target) {
                return 0;
            }
            // 递归查找左子树
            int left = findDepth(ancestor.left, target);
            // 如果在左子树中找到目标节点,返回左子树深度+1
            if (left != -1) {
                return left + 1;
            }
            // 递归查找右子树
            int right = findDepth(ancestor.right, target);
            // 如果在右子树中找到目标节点,返回右子树深度+1,否则返回-1
            return right != -1 ? right + 1 : -1;
        }
    }
相关推荐
咖啡八杯6 分钟前
GoF设计模式——解释器模式
java·后端·spring·设计模式
优橙教育18 分钟前
5G网优培训 vs Java开发:转行选哪个?
java·开发语言·5g
腻害兔2 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:字典、短信、邮件、通知——后台系统的“基础设施四件套“!
java·前端·vue.js·产品经理·ai编程
SeaTunnel2 小时前
从 Python Script 地狱到标准化数据集成框架
大数据·开发语言·python·程序员·代码·seatunnel
碎光拾影2 小时前
ARM交叉工具链各工具作用及IMX6ULL平台LED+蜂鸣器裸机程序实现
java·开发语言·数据库
Marst Code3 小时前
(python)2026Plotly 库评估:交互式可视化到底值不值得引入?
开发语言·python
Miao121313 小时前
微服务 API 测试实践:海外某民宿平台如何构建模式驱动测试基础设施
java·开发语言
腻害兔3 小时前
【若依项目-产品经理视角】RuoYi-Vue-Pro 源码拆解:支付模块 yudao-module-pay,一个让产品经理都看懂的支付中台设计
java·前端·vue.js·产品经理·ai编程
CRMEB系统商城4 小时前
开源自建还是SaaS订阅?算一笔3年经济账
java·大数据·开发语言·开源
keyipatience6 小时前
线程栈与TLS和线程互斥
java·linux·服务器·开发语言·ubuntu