• 二叉树最近的公共祖先[后序遍历与回溯模型的考察]


    前言

    二叉树问题都可分类于,前序与dfs/中序与平衡二叉/后序与回溯/层序与bfs。二叉树最近的公共祖先,用回溯时寻找到的祖先体现为最近祖先。

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

    在这里插入图片描述

    二、直接法 & 回溯模型

    1、直接法

    按后序遍历的节点顺序,以每个节点作为root,寻找左右节点,当两个都找到了则该root为最近公共祖先。

    // 二叉树的最近公共祖先。
    public class LowestCommonAncestor {
        // 按后序遍历的节点顺序,以每个节点作为root,寻找左右节点,当两个都找到了则该root为最近公共祖先。
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root == null) return null;
    
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            if (left != null) return left;
            TreeNode right = lowestCommonAncestor(root.right, p, q);
            if (right != null) return right;
    
            flag1 = flag2 = false;
            order(root, p, q);
            return flag1 && flag2 ? root : null;
        }
    
        boolean flag1, flag2;// 标记两个是否都找到了。
    
        private void order(TreeNode root, TreeNode p, TreeNode q) {
            if (root == null) return;
            if (root == p) flag1 = true;
            if (root == q) flag2 = true;
    
            order(root.left, p, q);
            order(root.right, p, q);
        }
    
        // Definition for a binary tree node.
        public class TreeNode {
            int val;
            TreeNode left;
            TreeNode right;
    
            TreeNode(int x) {
                val = x;
            }
        }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    2、回溯模型(合并if)

    利用回溯时判定左右两边是否都找到了。(后序遍历与回溯模型的考察。)

    两种情况,p/q有一个作为它们俩的最近公共祖先;有个root的左右子树上挂着p/q;

    第一种情况:率先找到那个就是它俩公共祖先;第二种情况:回溯时左右子树都找到了,返回root即可。

    注:左子树找到了root,就不用再遍历右边的所有右子树了,这部分可以剪枝。

    // 利用回溯时判定左右两边是否都找到了。(后序遍历与回溯模型的考察。)
    // 两种情况,p/q有一个作为它们俩的最近公共祖先;有个root的左右子树上挂着p/q;
    // 第一种情况:率先找到那个就是它俩公共祖先;第二种情况:回溯时左右子树都找到了,返回root即可。
    // 注:左子树找到了root,就不用再遍历右边的所有右子树了,这部分可以剪枝。
    class LowestCommonAncestor2 {
        public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
            if (root == null || isFind) return null;// 剪枝。
            if (root == p || q == root) return root;
    
            TreeNode left = lowestCommonAncestor(root.left, p, q);
            TreeNode right = lowestCommonAncestor(root.right, p, q);
    
            // 一个在左,一个在右,root就是最近公共祖先。
            if (left != null && right != null) {
                isFind = true;
    
                return root;
            }
            return left != null ? left : right;
        }
    
        boolean isFind = false;// 找到了设个标记,方便剪枝。
    
    
        // Definition for a binary tree node.
        public class TreeNode {
            int val;
            TreeNode left;
            TreeNode right;
    
            TreeNode(int x) {
                val = x;
            }
        }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34

    总结

    1)二叉树问题,莫过于前序与dfs/中序与平衡二叉/后序与回溯/层序与bfs。
    2)9个月前写的回溯模型,回溯时有left/right是否为null的四种情况判定,意味着4个if,现在很容易就把if合并,写出更简洁的代码,所以要多练才会灵活,思路才能打开 & 寻找到联系之处。

    参考文献

    [1] LeetCode 二叉树最近的公共祖先

  • 相关阅读:
    2023.11.16 hivesql之条件函数,case when then
    spark sql如何行转列
    代码随想录算法训练营第十四天|二叉树理论基础|二叉树的递归遍历|二叉树的迭代遍历以及统一迭代
    手写简单promise
    云小课|帮您高效快速上传组件至私有依赖库
    使用mysql语句对分组结果进行再次筛选
    【C语言】C语言文件操作详解(一)
    Python很慢,但它即将变得更快
    P1449 后缀表达式
    您遇到过网页抓取时被封IP的情况吗?
  • 原文地址:https://blog.csdn.net/qq_43164662/article/details/126175414