Blage's Coding Blage's Coding
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
Home
算法
  • 手写Spring
  • SSM
  • SpringBoot
  • JavaWeb
  • JAVA基础
  • 容器
  • Netty

    • IO模型
    • Netty初级
    • Netty原理
  • JVM
  • JUC
  • Redis基础
  • 源码分析
  • 实战应用
  • 单机缓存
  • MySQL

    • 基础部分
    • 实战与处理方案
    • 面试
  • ORM框架

    • Mybatis
    • Mybatis_Plus
  • SpringCloudAlibaba
  • MQ消息队列
  • Nginx
  • Elasticsearch
  • Gateway
  • Xxl-job
  • Feign
  • Eureka
  • 面试
  • 工具
  • 项目
  • 关于
🌏本站
🧸GitHub (opens new window)
  • 数组

  • 链表

  • 字符串

  • 二叉树

    • 102.二叉树的层序遍历
    • 103.二叉树的锯齿形层序遍历
    • 124.二叉树中的最大路径和
    • 236.二叉树的最近公共祖先
      • 1.一刷
      • 2.二刷
    • 105.从前序与中序遍历序列构造二叉树
    • 662.二叉树最大宽度
    • 1080. 根到叶路径上的不足节点
    • 101. 对称二叉树
    • 226. 翻转二叉树
    • 114. 二叉树展开为链表
    • 1110. 删点成林
    • 337. 打家劫舍 III
    • 979. 在二叉树中分配硬币
    • 222. 完全二叉树的节点个数
    • 513. 找树左下角的值
    • 968. 监控二叉树
    • 剑指offer34
    • 剑指 Offer 32 - III. 从上到下打印二叉树 III
    • 剑指 Offer 33. 二叉搜索树的后序遍历序列
    • 线索二叉树

    • 二叉搜索树

  • 动态规划

  • 深搜回溯

  • 数学贪心

  • 堆栈队列

  • 前缀和

  • 算法设计

  • 位运算

  • WA

  • 算法
  • 二叉树
phan
2023-05-16
目录

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

# 236.二叉树的最近公共祖先

给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5

# 1.一刷

  1. 一开始的想法是通过二叉树顺序存储的下标找到最近公共祖先。分为两个操作,首先需要遍历整个二叉树找到p和q对应的索引下标,再根据pnum=(pnum-1)/2得到父节点索引下标,直至pnum=qnum就得到最近的公共祖先的索引下标。但是不知道是我写的有问题,还是题目给的一个例子有问题(感觉是用例bug),[-1,0,null,1,null,2,null,3,null,4,null,5,null,6,null,7,null,8,null...]这个用例没能通过。(这用例给的是棵什么鬼树???还是说它想表达的是一颗链状树?)。总之要点在于:
  • left=pnum*2+1; right=pnum*2+2; parent=(pnum-1)/2
  1. 另一种思路是用哈希表记录当前节点值和父节点的关系HashMap<Integer p.val,TreeNode p.parent >;再用一个队列存放p的父节点,别忘记要先把p自身放入队列中。当list.contains(hashmap.get(q.val))时则找到最近公共祖先。

  2. 最优的方法是后序遍历。后序遍历的特点是先递归后处理,天然的自底向上二叉树回溯,最先处理的一定是叶子节点,写法如下:

    • 确定终止退出条件
    • 递归调用
    • 处理节点

    当一发现一个节点左子树有p,右子树有q节点,那么这个节点就是最近的公共祖先,因为后序遍历是从底向上找,所以找到的一定是最深的。难点的在于当左子树和右子树一边找到p另一边什么都没找到返回null时,这时候函数直接返回找到的p或者q节点,这个节点依旧具有深度最深的特性。

    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
                if(root==null)
                return null;
                if(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 root;
                if(left==null&&right==null)
                return null;
                return (right!=null)?right:left;
    
        }
    
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14

# 2.二刷

分析:如果以当前节点为根的子树,包含p节点或者q节点,则返回true。

那么最近公共祖先节点无非就以下两种情况:

  • 左子树为true,同时右子树为true
  • 左子树或者右子树存在一个true,然后当前root节点为pq其中一个节点。
class Solution {
      TreeNode res;
    public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {
        dfs(root,p,q);
        return res;
    }
    public boolean dfs(TreeNode root, TreeNode p, TreeNode q){
        boolean left=root.left==null?false:dfs(root.left,p,q);
        boolean right=root.right==null?false:dfs(root.right,p,q);
        if(left&&right){
            res=root;
            return true;
        }
        if(left||right){
            if(root==q||root==p) res=root;
            return true;
        }
        if(root==q||root==p) return true;
        return false;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
编辑 (opens new window)
#Leetcode#二叉树
上次更新: 2023/12/15, 15:49:57
124.二叉树中的最大路径和
105.从前序与中序遍历序列构造二叉树

← 124.二叉树中的最大路径和 105.从前序与中序遍历序列构造二叉树→

Theme by Vdoing | Copyright © 2023-2024 blageCoder
  • 跟随系统
  • 浅色模式
  • 深色模式
  • 阅读模式