• 力扣236题、235(二叉树最近公共祖先)


    看的代码随想录的解析

    236、二叉树的最近公共祖先

    基本思想:

    自底向上查找,就可以找到公共祖先

    回溯就是自底向上

    后序遍历是天然的回溯过程,最先处理的一定是叶子节点

    具体实现:

    找到一个节点,左子树出现节点p,右子树出现节点q(反过来也行),那么该节点就是节点p和q的最近公共祖先。

    递归三步:

    1、返回值以及参数

    返回值:

    3种情况,找到最近公共节点,返回最近公共节点

    遇到p或q,返回p或q

    啥也没找到,返回空

    这道题遍历了整棵二叉树,一般这种情况是不需要返回值的,

    但是,这道题回溯的过程需要递归函数的返回值做判断

    参数:

    根节点,p,q

    2、确定终止条件

    找到p或q,或者空节点,结束递归

    3、确定单层递归逻辑

    开始了一个很长的解释,,,,,,,,

    本题函数有返回值,是因为回溯的过程需要递归函数的返回值做判断,但本题我们依然要遍历树的所有节点。

    (1)递归函数有返回值的两种情况

    a、搜索一条边的写法

     b、搜索整个树的写法

     区别:

    在递归函数有返回值的情况下:
    如果要搜索⼀条边,递归函数返回值不为空的时候,⽴刻返回,
    如果搜索整个树,直接⽤⼀个变量left、right接住返回值,这个left、right后序还有逻辑处理的需要,也就是后序遍历中处理中间节点的逻辑(也是回溯)。

    (2)为什么要遍历整棵树?

    因为我们需要对left和right节点进行逻辑处理

    而只遍历一条边的写法会直接返回,并不能进行逻辑处理。

    用left,right接住左子树和右子树的返回值

     (3)逻辑处理

    如果left和right都不为空,此时的root就是最近公共节点

    如果left为空,right不为空,返回right,

    如果right为空,left不为空,返回left。

     (4)总结

    a、求最小公共祖先,需要从底向上遍历,只能通过后序遍历实现

    b、在回溯的过程中,必然要遍历整颗二叉树,即使找到结果了,依然要把其他节点遍历玩,因为要是用递归函数的返回值(left,right)做逻辑判断

    代码:

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            return lowestCommonAncestor1(root,p,q);
        }
        public TreeNode lowestCommonAncestor1(TreeNode root, TreeNode p, TreeNode q){
            if (root == null || root == p || root == q){
                return root;
            }
            TreeNode left = lowestCommonAncestor1(root.left,p,q);
            TreeNode right = lowestCommonAncestor1(root.right ,p, q);
            if (left != null && right != null){
                return root;
            }
            if (left == null){
                return right;
            }
            return left;
        }
    }

    235、二叉搜索树的最近公共祖先

    基本思想:

    普通二叉树求最近公共祖先需要使用回溯,从底向上来查找,

    二叉搜索树就不用了,因为搜索树有序(相当于自带方向),那么只要从上向下遍历就可以了。

    具体实现:

    1、确定递归函数返回值以及参数

    参数:当前节点以及两个节点p,q

    返回最近公共祖先

    2、确定终止条件:无

    3、单层递归逻辑

    在遍历二叉搜索树的时候就是寻找区间[p.val, q.val]

    如果 cur.val 大于 p.val,同时 cur.val 大于q.val,那么就应该向左遍历(说明目标区间在左子树上)。

    需要注意的是此时不知道p和q谁大,所以两个都要判断

    本题是标准的搜索一条边的写法,遇到递归函数的返回值,不为空,立刻就返回

    代码:

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root.val > p.val && root.val > q.val) return lowestCommonAncestor(root.left, p, q);
            if (root.val < p.val && root.val < q.val) return lowestCommonAncestor(root.right, p, q);
            return root;
        }
    }

    迭代法:

    class Solution {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            while (true) {
                if (root.val > p.val && root.val > q.val) {
                    root = root.left;
                } else if (root.val < p.val && root.val < q.val) {
                    root = root.right;
                } else {
                    break;
                }
            }
            return root;
        }
    }
  • 相关阅读:
    c#时间函数
    .NET中的lock(C#版本)
    关于OpenSmtp邮件标题过长,附件名,用户名出现乱码问题的终及解决Dll文件
    Windbg 用法
    使用OpenXML将数据导入到Excel模板中
    Compiere源码workspace的两个配置文件内容
    我学MEF系列(8):MEF+Unity实现可扩展拦截器
    基于插件架构的简单的Winform框架(上)
    我学Flash/Flex(2):AS3读取XML文件内容
    我学Flash/Flex(1):Action Script3.0基础知识
  • 原文地址:https://www.cnblogs.com/zhaojiayu/p/15380698.html
Copyright © 2020-2023  润新知