[剑指offer]面试题第[68-2]题[Leetcode][第236题][JAVA][二叉搜索树的最近公共祖先][递归]

38 篇文章 1 订阅
【问题描述】[中等]

235/68-1 搜索二叉树 236/68-2 二叉树
在这里插入图片描述

【解答思路】

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

递归

时间复杂度:O(N) 空间复杂度:O(N)
在这里插入图片描述

情况 1. , 2. , 3. , 4. 的展开写法如下。

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) return root;
        TreeNode left = lowestCommonAncestor(root.left, p, q);
        TreeNode right = lowestCommonAncestor(root.right, p, q);
        if(left == null && right == null) return null; // 1.
        if(left == null) return right; // 3.
        if(right == null) return left; // 4.
        return root; // 2. if(left != null and right != null)
    }
}




优化版

class Solution {
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        if(root == null || root == p || root == q) 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,从底至顶回溯,代码简单,但是分析起来复杂;
    //当root==null时,说明当前路径没有找到p或者q
    //当root==p||root==q,假设先找到的是节点p:
    //则继续从找到的节点p开始寻找另一个节点q(迭代),当第二个节点q也找到时,进行回溯,一开始回溯时,会一直保持单侧子树不为null的情况,但是注意这种情况,不是由于p,q均在当前单侧子树造成的,当前回溯过程的单侧子树内只有一个q;
    //继续回溯,当回溯至一个节点root时,节点 p,q在节点root的异侧,即双侧子树均不为null时,节点 root即为最近公共祖先。
    //返回root,后续则又会变为单侧子树不为null,这时才是因为p,q均在当前单侧子树造成的;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        //root=null,返回root说明这条路径没有找到p或者q;root=p||root=q时说明当前找到了p或者q;
    	if(root==null||root==p||root==q) return root;
        TreeNode left = lowestCommonAncestor(root.left,p,q);
        TreeNode right = lowestCommonAncestor(root.right,p,q);
        //后面是回溯过程,下面三个if语句可以交换顺序,如果固定顺序,则后面两个if可以进行简化
        //当root的左子树和右子树都没有p或者q时,root不是p和q祖先,返回null;
        if(left==null&&right==null) return null;
        
        //基于第一个if,这里的if可以简写为if(right==null) return left;
        //这里root的右子树没有找到p或者q,left找到了p或者q,这里返回的left有两种情况:
        //1.未找到最近公共节点时,即还在迭代阶段,这里返回的left为找到的p(假设为p),即第一个if的return结果:
        //若前面没有找到q,则从p开始继续进行迭代,在二叉树中剩余的节点中找到剩下的那个q;  若之前已经找到了q,则开始返回,直到找到left!=null&&right!=null,即找到了最近公共祖宗;
        //2.找到最近公共节点时,即处于返回阶段,不需要再进行迭代了,此时p,q在同一侧子树中,这里left为找到的最近公共节点,即下面最后一个return的结果;
        if(left!=null&&right==null) return left;
        //基于第一个if,这里的if可以简写为if(left==null) return right;
        //这里的分析和上面一个if类似;
        if(left==null&&right!=null) return right;
        return root;//即if(left!=null&&right!=null) return root;但注释中的写法会使得函数缺少return语句;
    }




【总结】
1. 二叉树遍历

前序遍历 先输出当前结点的数据,再依次遍历输出左结点和右结点
中序遍历 先遍历输出左结点,再输出当前结点的数据,再遍历输出右结点
后续遍历 先遍历输出左结点,再遍历输出右结点,最后输出当前结点的数据

2. 对于二叉树的题,开始可以用递归的思想去思考单 代码简单 过程不简单
3. 相关题目[剑指offer]面试题第[68-1]题[Leedcode][JAVA][第235题][二叉搜索树的最近公共祖先][递归][BFS]

作者:Krahets
转载链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-er-cha-shu-de-zui-jin-gong-gon-7/

参考链接:https://leetcode-cn.com/problems/er-cha-shu-de-zui-jin-gong-gong-zu-xian-lcof/solution/mian-shi-ti-68-ii-javashi-xian-jian-zhi-offersi-lu/

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值