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

前言

二叉树问题都可分类于,前序与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;
        }
    }
}

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

参考文献

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值