前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >专栏 >LeetCode 236:二叉树的最近公共祖先

LeetCode 236:二叉树的最近公共祖先

作者头像
Wu_Candy
发布于 2022-07-04 13:07:05
发布于 2022-07-04 13:07:05
32200
代码可运行
举报
文章被收录于专栏:无量测试之道无量测试之道
运行总次数:0
代码可运行
这是无量测试之道的第216篇原创

特别说明:

输入:root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 4 输出:5 解释:节点 5 和节点 4 的最近公共祖先是节点 5 。因为根据定义最近公共祖先节点可以为节点本身。


解题思路:

  一般二叉树相关的算法题,都可以使用递归这个编程技巧来解题,本题也不例外。

分析: 2个节点存在的位置,不外乎以下4种情况:

  1. 要么都在左子树上
  2. 要么都在右子树上
  3. 要么一个在左,一个在右
  4. 至少有一个不在这颗二叉树中【就是不在这个二叉树上的情况

我们先看代码,然后来讲解解法,代码如下:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/**
 * Definition for a binary tree node.
 * public class TreeNode {
 *     public var val: Int
 *     public var left: TreeNode?
 *     public var right: TreeNode?
 *     public init(_ val: Int) {
 *         self.val = val
 *         self.left = nil
 *         self.right = nil
 *     }
 * }
 */

class Solution {
    func lowestCommonAncestor(_ root: TreeNode?, _ p: TreeNode?, _ q: TreeNode?) -> TreeNode? {
        if root == nil || root?.val == p?.val || root?.val == q?.val { return root }
        let left = lowestCommonAncestor(root?.left, p, q)
        let right = lowestCommonAncestor(root?.right, p, q)
        if left != nil && right != nil { return root }
        return left == nil ? right : left
    }
}

代码解析: 先是边界条件的判断    1. if root为nil,直接 return    2. if root.val == q.val 或者 root.val == p.val,直接 return

下面是递归逻辑:    1. 先从左子树上找共同的祖先,记为left    2. 再从右子树上找共同的祖先,记为right

   如果left和right都不为nil,说明满足上述的条件3【一个在左,一个在右】,所以很显然,祖先节点就是根节点root;

   如果left不为nil,则返回left,否则返回right。这里面就包含了剩下3种条件,left不为nil,说明2个节点都在左子树上。如果left为nil,则说明要么2个节点都在右子树上,或者至少有一个不在这个二叉树上。

关于递归:

   递归这种编程技巧是非常有用的,掌握它,可以为我们解决很多思考起来很麻烦的题目。为了更好的理解递归,大家可以看我之前写的文章:leetcode 递归编程技巧-链表算法题。为了让大家体会到递归的强大,我们再看1道题: LeetCode 144. 二叉树的前序遍历 如下图:一颗二叉数

前序遍历就是:先访问节点、前序遍历子树、前序遍历子树。 过程如下:

  1. 先访问5,然后使用中序遍历去访问 5.left,再然后使用前序遍历去访问 5.right。 1.1. 中序遍历去访问5.left 先访问3,然后使用中序遍历去访问 3.left,再然后使用前序遍历去访问 3.right。 ... ... 1.2. 中序遍历去访问5.right 先访问7,然后使用中序遍历去访问 7.left,再然后使用前序遍历去访问 7.right。 ... ...

打印结果就是:5-3-1-0-2-4-7-6-8-9

代码:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    var nums = [Int]()
    func inorderTraversal(_ root: TreeNode?) -> [Int] {
    guard let root = root else { return [] }
            nums.append(root.val)
            inorderTraversal(root.left)
            inorderTraversal(root.right)
    return nums
        }
}

代码解析: 先是边界条件的判断    1. 先访问根节点    2. 然后前序遍历左子树    2. 然后前序遍历右子树

如果问你中序遍历【左根右】,你会写吗?

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
class Solution {
    var nums = [Int]()
    func inorderTraversal(_ root: TreeNode?) -> [Int] {
    guard let root = root else { return [] }
            inorderTraversal(root.left)
            nums.append(root.val)
            inorderTraversal(root.right)
    return nums
        }
}

  对,你没看错。就是这么简单,把它的访问放在中间就是【以后写一些算法的时候,可以把逻辑写在中间】。那么后序遍历了?一样,把访问 nums.append(root.val) 代码放在最后一行就是了。这就是递归的魅力。

总结:

  今天主要讲了一道leetcode上面的第236道算法题,其核心思想就是使用递归来实现的。后续为了让大家体会到递归编程技巧的强大,我又借二叉树的遍历例子用递归来实现为大家展示递归的强大。大家如果想更好的理解递归的调用栈的话,可以看我自己写的文章:leetcode 递归编程技巧-链表算法题。希望能帮助到大家。

end

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2021-06-22,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 无量测试之道 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
LeetCode初中级算法题解 - 二叉树篇
  搜集题目的难度是在简单级别和中级级别,也是面试常考的题目。题目的题解,使用的开发语言是Swift。
Wu_Candy
2022/07/04
1440
LeetCode通关:连刷三十九道二叉树,刷疯了!
大家好,我是拿输出博客来督促自己刷题的老三,这一节我们来刷二叉树,二叉树相关题目在面试里非常高频,而且在力扣里数量很多,足足有几百道,不要慌,我们一步步来。我的文章很长,你们 收藏一下。
三分恶
2021/09/08
8470
二叉树经典OJ题(2)
技巧:在递归过程中,我们想要有一个变量记录全过程(该题中的prev),第一种方法就是设置成全局变量,第二种方法就是传引用。
小陈在拼命
2024/04/20
670
二叉树经典OJ题(2)
Js算法与数据结构拾萃(4):二叉树
因此只要答对这道题,你就可以超越世界级大牛,问鼎码林之巅(逃) 导读: •二叉树知识重点•二叉树深度不一,因此天生适用递归,因此可用递归处理•判断两树相等•翻转二叉树•二叉树三种深度遍历(迭代)•前序遍历•中序遍历•后序遍历•二叉树的一些迭代特性•判断是否二叉搜索树•二叉搜索树的最近公共祖先•二叉树的最近公共祖先
一粒小麦
2020/02/25
6450
C++【二叉树进阶试题】
这是一篇关于 二叉树 题解博客,主要包含以下题目,可根据当前文章中的目录随意跳转查看
北 海
2023/07/01
2560
C++【二叉树进阶试题】
LeetCode-236-二叉树的最近公共祖先
百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点也可以是它自己的祖先)。”
benym
2022/07/14
2530
LeetCode 二叉树系统题解
TIPS:前中后序遍历区别在于三字中的中间那个字,前、中、后序分别对应左、根、右。
Yano_nankai
2019/11/10
9680
LeetCode 二叉树系统题解
C++: 二叉树进阶面试题
根据前序遍历创建二叉树, 再递归子树之前需要加括号, 但是题目要求省略不必要的括号, 通过观察可发现
用户11317877
2024/10/16
710
C++: 二叉树进阶面试题
【算法】二叉树遍历算法总结:前序中序后序遍历
但是在平常的笔试面试中,其出现的频率其实并不是特别的高,我推测是这种题目相对来说比较基础,算是一个基础知识点。
蛮三刀酱
2020/02/25
1.2K0
【算法】二叉树遍历算法总结:前序中序后序遍历
总结了一些二叉树操作的干货……
导读:二叉树是一种经典的数据结构,其概念本身不难理解,但因其结构的特殊性,许多操作都有着非常精妙的技巧。结合最近LeetCode中的一些相关题目,简要记录一些个人觉得比较巧妙的编程实现。
luanhz
2020/04/01
2950
求二叉树的最近公共祖先,倘若不是二叉树呢?
如果给定以下搜索二叉树: {7,1,12,0,4,11,14,#,#,3,5},如下图:
秦怀杂货店
2022/02/17
4760
求二叉树的最近公共祖先,倘若不是二叉树呢?
【Leetcode】二叉树的最近公共祖先,二叉搜索树转换成排好序的双向链表,前序遍历与中序遍历构造二叉树
观察上图,节点1和节点4的最近公共祖先是3,这是不是很像相交链表的问题,关于相交链表,曾经我在另一篇文章里写到过,读者可以参考:反转链表 合并链表 相交链表
aosei
2024/01/23
1820
【Leetcode】二叉树的最近公共祖先,二叉搜索树转换成排好序的双向链表,前序遍历与中序遍历构造二叉树
二叉树的四种遍历方式以及层序、前中、后中、前后方式创建二叉树【专为力扣刷题而打造】
这里三种遍历方式不用过多介绍,相信学过数据结构的人都可以轻松使用递归方式进行遍历,非递归方式思想也是一致的。根据前序中序、中序后序、前序后序均参考力扣题解所写,只有层序遍历是为了再力扣解题不方便所以才选择在本地解题,但是本地解题不能进行测试,使用其他三种创建方式又过于麻烦,所以想使用层序创建二叉树,思维比较简单供大家参考,有问题可以及时讨论。
了凡银河系
2022/08/22
3100
二叉树的四种遍历方式以及层序、前中、后中、前后方式创建二叉树【专为力扣刷题而打造】
二叉树oj以及前中后序非递归写法
给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。
始终学不会
2023/10/17
2060
二叉树oj以及前中后序非递归写法
LeetCode | 94.二叉树的中序遍历
这次来写一下 LeetCode 的第 94 题,二叉树的中序遍历。
码农UP2U
2020/10/14
4200
LeetCode | 94.二叉树的中序遍历
LeetCode——根据二叉树创建字符串与二叉树的最近公共祖先
给你二叉树的根节点 root ,请你采用前序遍历的方式,将二叉树转化为一个由括号和整数组成的字符串,返回构造出的字符串。
有礼貌的灰绅士
2023/04/17
1800
LeetCode——根据二叉树创建字符串与二叉树的最近公共祖先
JavaScript算法题总结 (三)二叉树
BM23 二叉树的前序遍历 /* * function TreeNode(x) { * this.val = x; * this.left = null; * this.right = null; * } */ /** * 代码中的类名、方法名、参数名已经指定,请勿修改,直接返回方法规定的值即可 * * * @param root TreeNode类 * @return int整型一维数组 */ function preorderTraversal( root )
henu_Newxc03
2022/05/12
2510
JavaScript算法题总结 (三)二叉树
精读《算法 - 二叉树》
二叉树是一种数据结构,并且拥有种类复杂的分支,本文作为入门篇,只介绍一些基本二叉树的题型,像二叉搜索树等等不在此篇介绍。
黄子毅
2022/03/15
3050
二叉树各种遍历真的很难?大sai带你拿捏!
很多时候我们需要使用非递归的方式实现二叉树的遍历,非递归枚举相比递归方式的难度要高出一些,效率一般会高一些,并且前中后序枚举的难度呈一个递增的形式,非递归方式的枚举有人停在非递归后序,有人停在非递归中序,有人停在非递归前序(这就有点拉胯了啊兄弟)。
bigsai
2021/10/08
6830
二叉树各种遍历真的很难?大sai带你拿捏!
几道和「二叉树」有关的算法面试题
在遍历到一个结点之前已经遍历了它的左右子树,那么只要在遍历每个结点的时候记录它的深度(某一结点的深度等于它到叶结点的路径的长度),就可以一边遍历一边判断每个结点是不是平衡的。
五分钟学算法
2019/03/30
9080
推荐阅读
相关推荐
LeetCode初中级算法题解 - 二叉树篇
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档