力扣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;
    }
}
原文地址:https://www.cnblogs.com/zhaojiayu/p/15380698.html