2024.2.9力扣每日一题——二叉树的最近公共祖先

2024-04-01 15:20

本文主要是介绍2024.2.9力扣每日一题——二叉树的最近公共祖先,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

2024.2.9

      • 题目来源
      • 我的题解
        • 方法一 后序遍历
        • 方法二 存储父节点(哈希表+List)

题目来源

力扣每日一题;题序:236

我的题解

方法一 后序遍历

后序遍历可以携带一些子节点信息,通过后序遍历可以知道节点p和节点q在根节点的哪个子节点出现。

时间复杂度:O(n)。
空间复杂度:O(n)。递归调用的栈深度取决于二叉树的高度,二叉树最坏情况下为一条链,此时高度为 n,因此空间复杂度为 O(n)

TreeNode res=null;
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {find(root,p,q);return res;
}
public boolean find(TreeNode root,TreeNode p,TreeNode q){if(root==null){return false;}//看p或者q是否在左子树出现boolean lson=find(root.left,p,q);//看p或者q是否在右子树出现boolean rson=find(root.right,p,q);//lson&&rson表示p和q分别出现在root的左右子树上//(root==p||root==q)&&(lson||rson) 表示root就是p或者q,并且q或p在root的某一个子树上if((lson&&rson)||((root==p||root==q)&&(lson||rson))){res=root;}return lson||rson||(root==p||root==q);
}
方法二 存储父节点(哈希表+List)

类似并查集的操作。这里使用哈希表存储每个节点的父节点,然后利用节点的父节点信息从 p 结点开始不断往上跳,并记录已经访问过的节点,再从 q 节点开始不断往上跳,如果碰到已经访问过的节点,那么这个节点就是要找的最近公共祖先。
具体做法

  • 从根节点开始遍历整棵二叉树,用哈希表记录每个节点的父节点指针。
  • 从 p 节点开始不断往它的祖先移动,并用数据结构记录已经访问过的祖先节点。
  • 同样,再从 q 节点开始不断往它的祖先移动,如果有祖先已经被访问过,即意味着这是 p 和 q 的深度最深的公共祖先,即 LCA 节点。

时间复杂度:O(n)
空间复杂度:O(n)

Map<TreeNode,TreeNode> map=new HashMap<>();
public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {dfs(root,null);List<TreeNode> hasVisited=new ArrayList<>();//找寻p节点的所有祖先节点TreeNode pParent=map.get(p);//注意p本身是最近公共祖先节点hasVisited.add(p);while(pParent!=null){hasVisited.add(pParent);pParent=map.get(pParent);}//注意q本身就是最近公共祖先节点if(hasVisited.contains(q))return q;//遍历q的祖先节点TreeNode qParent=map.get(q);while(qParent!=null){if(hasVisited.contains(qParent))return qParent;qParent=map.get(qParent);}return root;
}
//存储父节点
public void dfs(TreeNode root,TreeNode parent){if(root==null)return ;map.put(root,parent);dfs(root.left,root);dfs(root.right,root);
}

有任何问题,欢迎评论区交流,欢迎评论区提供其它解题思路(代码),也可以点个赞支持一下作者哈😄~

这篇关于2024.2.9力扣每日一题——二叉树的最近公共祖先的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/867499

相关文章

SpringBoot自定义注解如何解决公共字段填充问题

《SpringBoot自定义注解如何解决公共字段填充问题》本文介绍了在系统开发中,如何使用AOP切面编程实现公共字段自动填充的功能,从而简化代码,通过自定义注解和切面类,可以统一处理创建时间和修改时间... 目录1.1 问题分析1.2 实现思路1.3 代码开发1.3.1 步骤一1.3.2 步骤二1.3.3

最长公共子序列问题的深度分析与Java实现方式

《最长公共子序列问题的深度分析与Java实现方式》本文详细介绍了最长公共子序列(LCS)问题,包括其概念、暴力解法、动态规划解法,并提供了Java代码实现,暴力解法虽然简单,但在大数据处理中效率较低,... 目录最长公共子序列问题概述问题理解与示例分析暴力解法思路与示例代码动态规划解法DP 表的构建与意义动

poj1330(LCA最近公共祖先)

题意:求最近公共祖先 思路:之前学习了树链剖分,然后我就用树链剖分的一小部分知识就可以解这个题目了,记录每个结点的fa和depth。然后查找时,每次将depth大的结点往上走直到x = y。 代码如下: #include<iostream>#include<algorithm>#include<stdio.h>#include<math.h>#include<cstring>

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟)

【每日一题】LeetCode 2181.合并零之间的节点(链表、模拟) 题目描述 给定一个链表,链表中的每个节点代表一个整数。链表中的整数由 0 分隔开,表示不同的区间。链表的开始和结束节点的值都为 0。任务是将每两个相邻的 0 之间的所有节点合并成一个节点,新节点的值为原区间内所有节点值的和。合并后,需要移除所有的 0,并返回修改后的链表头节点。 思路分析 初始化:创建一个虚拟头节点

leetcode105 从前序与中序遍历序列构造二叉树

根据一棵树的前序遍历与中序遍历构造二叉树。 注意: 你可以假设树中没有重复的元素。 例如,给出 前序遍历 preorder = [3,9,20,15,7]中序遍历 inorder = [9,3,15,20,7] 返回如下的二叉树: 3/ \9 20/ \15 7   class Solution {public TreeNode buildTree(int[] pr

每日一题|牛客竞赛|四舍五入|字符串+贪心+模拟

每日一题|四舍五入 四舍五入 心有猛虎,细嗅蔷薇。你好朋友,这里是锅巴的C\C++学习笔记,常言道,不积跬步无以至千里,希望有朝一日我们积累的滴水可以击穿顽石。 四舍五入 题目: 牛牛发明了一种新的四舍五入应用于整数,对个位四舍五入,规则如下 12345->12350 12399->12400 输入描述: 输入一个整数n(0<=n<=109 ) 输出描述: 输出一个整数

每日一练7:简写单词(含链接)

1.链接 简写单词_牛客题霸_牛客网 2.题目 3.代码1(错误经验) #include <iostream>#include <string>using namespace std;int main() {string s;string ret;int count = 0;while(cin >> s)for(auto a : s){if(count == 0){if( a <=

两数之和--力扣1

两数之和 题目思路C++代码 题目 思路 根据题目要求,元素不能重复且不需要排序,我们这里使用哈希表unordered_map。注意题目说了只对应一种答案。 所以我们在循环中,使用目标值减去当前循环的nums[i],得到差值,如果我们在map中能够找到这个差值,就说明存在两个整数的和为目标值。 如果没有找到,就将当前循环的nums[i]以及下标i放入map中,以便后续查

【每日刷题】Day113

【每日刷题】Day113 🥕个人主页:开敲🍉 🔥所属专栏:每日刷题🍍 🌼文章目录🌼 1. 91. 解码方法 - 力扣(LeetCode) 2. LCR 098. 不同路径 - 力扣(LeetCode) 3. 63. 不同路径 II - 力扣(LeetCode) 1. 91. 解码方法 - 力扣(LeetCode) //思路:动态规划。 cl

PHP实现二叉树遍历(非递归方式,栈模拟实现)

二叉树定义是这样的:一棵非空的二叉树由根结点及左、右子树这三个基本部分组成,根据节点的访问位置不同有三种遍历方式: ① NLR:前序遍历(PreorderTraversal亦称(先序遍历)) ——访问结点的操作发生在遍历其左右子树之前。 ② LNR:中序遍历(InorderTraversal) ——访问结点的操作发生在遍历其左右子树之中(间)。 ③ LRN:后序遍历(PostorderT