题目

原题地址:leetcode 235. 二叉搜索树的最近公共祖先

说明:

  • 所有节点的值都是唯一的。
  • p、q 为不同节点且均存在于给定的二叉搜索树中。

题解

关于 树形dp 套路,可以参考我的另一篇博客:左神算法:找到二叉树中的最大搜索二叉子树(Java版)

下面简述本题思路:

  1. 首先,如何判断一个节点 head 是否是 p、q 的公共祖先?只需要用二分查找的方式,判断以 head 为头的树中是否包含 p、q 即可。
  2. 然后,如何找到“最近”的公共祖先?直观上看,最近的公共祖先,一定是所有的公共祖先中 最深的那个。因此,只需要遍历整个二叉树,就可以找到最深的公共祖先了,也就是我们所说的最近公共祖先。

总的来说,就是 利用递归函数设计一个二叉树前序遍历的过程:先收集当前节点的信息,然后根据当前节点的信息,去遍历左子树(同时更新信息),最后再遍历右子树(同时更新信息)

时间复杂度分析

因为是递归函数,所以对所有的子树要求一样,都返回 Record 的实例。依次求出每棵子树的答案,总答案一定在其中。既然是前序遍历,则时间复杂度为O(N)

代码如下,完整步骤见 lowestCommonAncestor 函数。

代码

// Definition for a binary tree node.
class TreeNode {int val;TreeNode left;TreeNode right;TreeNode(int x) {val = x;}
}public class Solution {// for testpublic static void main(String[] args) {TreeNode n0 = new TreeNode(0);TreeNode n1 = new TreeNode(1);TreeNode n2 = new TreeNode(2);TreeNode n3 = new TreeNode(3);TreeNode n4 = new TreeNode(4);TreeNode n5 = new TreeNode(5);TreeNode n6 = new TreeNode(6);TreeNode n7 = new TreeNode(7);TreeNode n8 = new TreeNode(8);TreeNode n9 = new TreeNode(9);n6.left = n2;n6.right = n8;n2.left = n0;n2.right = n4;n4.left = n3;n4.right = n5;n8.left = n7;n8.right = n9;int n = lowestCommonAncestor(n6, n2, n4).val;System.out.println(n); // 答案:2}/*** 自定义记录结构,方便引用传递时改变其值*/static class Record {TreeNode deepestNode; // 最深节点int deepestDepth; // 最深节点的深度public Record(TreeNode deepestNode, int deepestDepth) {this.deepestNode = deepestNode;this.deepestDepth = deepestDepth;}}/*** 入口*/public static TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {return preTree(root, p, q, new Record(root, 0), 0).deepestNode;}/*** 前续遍历所有二叉树节点,找最深且满足要求的head* (经过leetcode验证,此处也可以直接改成后序遍历,不影响结果正确性)* @param head 头结点* @param p 题目中要找的p* @param q 题目中要找的q* @param record 自定义记录结构* @param depth 当前深度* @return*/public static Record preTree(TreeNode head, TreeNode p, TreeNode q, Record record, int depth) {if (head == null) {return record;}// 先收集当前节点的信息depth += 1;if (isBSTNode(head, p) && isBSTNode(head, q)) { // 如果head为根的树中可以找到p、q,则说明满足要求if (depth > record.deepestDepth) { // 如果当前head的深度更深,则更新record.deepestNode = head;record.deepestDepth = depth;}}preTree(head.left, p, q, record, depth); // 根据当前节点信息,前序递归左子树preTree(head.right, p, q, record, depth); // 根据当前节点信息,前序递归右子树return record;}/*** 在以h为头结点的树中,用二叉搜索的方式能否找到节点n*/public static boolean isBSTNode(TreeNode h, TreeNode n) {if (h == null) {return false;}if (h == n) {return true;}return isBSTNode(h.val > n.val ? h.left : h.right, n);}
}

附:评论区的简洁解法

class Solution {public TreeNode lowestCommonAncestor(TreeNode root, TreeNode p, TreeNode q) {if (root == null) {return null;}if (p.val < root.val && q.val < root.val) {return lowestCommonAncestor(root.left, p, q);}if (p.val > root.val && q.val > root.val) {return lowestCommonAncestor(root.right, p, q);}return root;}
}

leetcode 235. 二叉搜索树的最近公共祖先(Java版,树形dp套路)相关推荐

  1. leetcode —— 235. 二叉搜索树的最近公共祖先

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖 ...

  2. Leetcode 235.二叉搜索树的最近公共祖先

    Time: 20190907 Type: Easy 题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p. ...

  3. leetcode 235. 二叉搜索树的最近公共祖先

    给定一棵二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义: "对于有根树T的两个结点u.v,最近公共祖先表示一个结点x,满足x是u.v的祖先且x的深度尽可能 ...

  4. leetcode 235. 二叉搜索树的最近公共祖先 思考分析

    目录 题目 思考 迭代法 题目 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 ...

  5. LeetCode 235. 二叉搜索树的最近公共祖先(递归)

    题目描述 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p ...

  6. ( “树” 之 BST) 235. 二叉搜索树的最近公共祖先 ——【Leetcode每日一题】

    二叉查找树(BST):根节点大于等于左子树所有节点,小于等于右子树所有节点. 二叉查找树中序遍历有序. 235. 二叉搜索树的最近公共祖先 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. ...

  7. 二叉树part8 | ● 235. 二叉搜索树的最近公共祖先 ● 701.二叉搜索树中的插入操作 ● 450.删除二叉搜索树中的节点

    文章目录 235. 二叉搜索树的最近公共祖先 思路 代码 困难 701.二叉搜索树中的插入操作 思路 代码 450.删除二叉搜索树中的节点 思路 代码 困难 今日收获 235. 二叉搜索树的最近公共祖 ...

  8. 【C语言刷LeetCode】235. 二叉搜索树的最近公共祖先(E)

    [ 给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q ...

  9. 【Leetcode | 235】 235. 二叉搜索树的最近公共祖先

    给定一个二叉搜索树, 找到该树中两个指定节点的最近公共祖先. 百度百科中最近公共祖先的定义为:"对于有根树 T 的两个结点 p.q,最近公共祖先表示为一个结点 x,满足 x 是 p.q 的祖 ...

最新文章

  1. Linux网络编程:基于UDP的程序开发回顾篇
  2. VSCode中屏蔽文件files.exclude和屏蔽文件搜索search.exclude
  3. asp.net mvc请求响应模型原理回顾
  4. mysql mmm 主主_Microsoft Azure部署MYSQL-MMM(2)配置主主复制
  5. HTML5_1 笔记
  6. 机器学习第三篇:详解朴素贝叶斯算法
  7. 2015-03-19 Opportunity order by implementation detail
  8. python加权最小二乘_【Python】统计科学之加权最小二乘法
  9. ETL(数据仓库技术)
  10. pytorch torch.normal
  11. java十进制转换成二进制数
  12. LeetCode Week 3:第 21 ~ 30 题
  13. 傅里叶分析 [作 者:韩 昊]
  14. Oracle触发器原理、创建、修改、删除
  15. 使用QGIS实现城市空气质量指数(AQI)数据可视化
  16. html超链接子页面,页面html超链接怎么做
  17. ARM Cortex M3处理器概述
  18. 02 C/C++创建tcl自定义命令
  19. 星际争霸兵种的诉苦(简略版)
  20. 幂函数与指数函数的近似

热门文章

  1. Fastai-竞赛实战
  2. 【数据结构】队列-顺序队列、循环队列、链队、双端队列
  3. 二进制位交换,反转,与统计1的个数
  4. 2017/9/26Codeforces E题
  5. IDA来远程调试Linux程序
  6. 80%的Linux都不懂的内存问题
  7. Linux调度系统全景指南(中篇)
  8. Java多线程知识小抄集(一)
  9. 【网络传输与RTC】
  10. 【大会】网络性能、安全与成本之困