寻找共同祖先

输入: root = [3,5,1,6,2,0,8,null,null,7,4], p = 5, q = 1
输出: 3
解释: 节点 5 和节点 1 的最近公共祖先是节点 3。

首先是需要构造树

class BinTNode:def __init__(self,data=None,left =None,right =None):self.data =dataself.left =leftself.right =rightdef buildTree1(arr,pointer,N):if pointer <=N:if arr[pointer] == -1:curNode = Noneelse:curNode = BinTNode(arr[pointer])if 2*pointer+1<=N:curNode.left = buildTree(arr,2*pointer+1,N)if 2*pointer+2<=N:curNode.right = buildTree(arr,2*pointer+2,N)return curNode# 如下是简化的版本,我们一般在循环里尽量少用判断语句
def buildTree(arr,pointer,N):# 递归出口,当越界时就没有必要创建节点了直接return,开始回退# 当值为-1时,也没有必要创建结点if pointer > N or arr[pointer] == -1:return NonecurNode = BinTNode(arr[pointer])curNode.left = buildTree(arr,2*pointer+1,N)curNode.right = buildTree(arr,2*pointer+2,N)return curNode

寻找两个孩子的共同祖先:我们定义问题为找共同祖先,当一颗子树只含有child1时,

那么这颗子树的祖先就是child1,一颗子树只含有child2时,那么这颗子树的祖先就是child2,

当一颗子树同时含有child1和child2时,那么他的祖先就是child1和child2的共同祖先,然后把问题缩小到一颗子树

def findAncestor(root,child1,child2):if not root:return -1# 把原问题分成三个部分,左子树,当前结点,右子树if root.data == child1 or root.data ==child2:# 不管下面还有没有要找的child,整颗树的祖先都是rootreturn root.data# 如果root不是任何一个的祖先,就需要处理下面的2颗子树left_ancestor = findAncestor(root.left,child1,child2)right_ancestor = findAncestor(root.right,child1,child2)# 然后基于两颗子树得到的结果处理,分为六种情况:# 左0右0,-1,                  left_ancestor + right_ancestor + 1# 左1右1,root.data,            root.data# 左1右0,left_ancestor         left_ancestor + right_ancestor + 1# 左0右1,right_ancestor        left_ancestor + right_ancestor + 1# 左2右0,left_ancestor         left_ancestor + right_ancestor + 1# 左0右2,right_ancestor        left_ancestor + right_ancestor + 1if left_ancestor !=-1 and right_ancestor !=-1:return root.data# 这个简化处理非常巧妙,一般写循环尽量少用判断,可以巧妙利用返回值-1构造通用结果# 看这个处理直接把其他的5种结果都处理成left_ancestor + right_ancestor + 1# 利用返回的结果为-1,+1之后可以消除可能出现的那个结果return left_ancestor + right_ancestor + 1# 这种方案存在问题,当一颗子树只含有child1时,
# 那么这颗子树的祖先就是child1,一颗子树只含有child2时,那么这颗子树的祖先就是child2,
# 但是最终方案是求共同祖先,如果输入一个孩子不存在,那返回结果不久变成了两外一个孩子def findAncestor2(root,child1,child2):# 把原问题分成三个部分,左子树,当前结点,右子树if (not root) or root.data == child1 or root.data ==child2:# 不管下面还有没有要找的child,整颗树的祖先都是root        return root# 如果root不是任何一个的祖先,就需要处理下面的2颗子树
#    left_ancestor =None
#    right_ancestor =Noneleft_ancestor = findAncestor2(root.left,child1,child2)right_ancestor = findAncestor2(root.right,child1,child2)# 然后基于两颗子树得到的结果处理,分为六种情况:# 左0右0,none,                [left_ancestor , right_ancestor]# 左1右1,root,                 root# 左1右0,left_ancestor         [left_ancestor , right_ancestor]# 左0右1,right_ancestor        [left_ancestor , right_ancestor ]# 左2右0,left_ancestor         [left_ancestor , right_ancestor]# 左0右2,right_ancestor        [left_ancestor , right_ancestor]if left_ancestor and right_ancestor:return root# 这个简化处理非常巧妙,一般写循环尽量少用判断,可以巧妙利用返回值-1构造通用结果# 看这个处理直接把其他的5种结果都处理成left_ancestor + right_ancestor + 1# 利用返回的结果为-1,+1之后可以消除可能出现的那个结果return (left_ancestor,right_ancestor)[not left_ancestor]# leetcode 236
# Definition for a binary tree node.
# class TreeNode:
#     def __init__(self, x):
#         self.val = x
#         self.left = None
#         self.right = None
class Solution:def lowestCommonAncestor(self, root, p, q):""":type root: TreeNode:type p: TreeNode:type q: TreeNode:rtype: TreeNode"""if (not root) or root.data == p or root.data ==q:   return rootleft_ancestor = self.lowestCommonAncestor(root.left,p,q)right_ancestor = self.lowestCommonAncestor(root.right,p,q)if left_ancestor and right_ancestor:return root# 比较三种情况的处理return left_ancestor if left_ancestor else right_ancestor

运行结果

arr =[1,2,3,4,5,6,7,-1,-1,8,9,-1,-1,10,11]
root = buildTree(arr,0,len(arr)-1)
print(findAncestor(root,9,5))
print(findAncestor2(root,9,5).data)
print(Solution().lowestCommonAncestor(root,9,5).data)runfile('D:/share/test/buildTree.py', wdir='D:/share/test')
5
5
5

这3种方案存在问题,当一颗子树只含有child1时,

那么这颗子树的祖先就是child1,一颗子树只含有child2时,那么这颗子树的祖先就是child2,

但是最终方案是求共同祖先,如果输入一个孩子不存在,那返回结果不久变成了两外一个孩子

树形结构:寻找共同祖先相关推荐

  1. 树形结构:从二分查找,二叉搜索树寻找最近祖先,从递归到迭代,实现技巧总结

    二分查找,二叉搜索树寻找最近祖先均是典型分治问题,把原问题分成三部分考虑,递归实现简单,迭代实现也比较简单,里面蕴含了一些从从递归到迭代的技巧,注意这里没有使用模拟栈技术. 深究其原因是,这一类型的递 ...

  2. 数据结构与算法之链表结构寻找p、q最近的公共祖先

    链表结构,寻找p.q最近的公共祖先 数据结构与算法之链表结构寻找p.q最近的公共祖先 链表结构,寻找p.q最近的公共祖先 问题 想法 代码 问题 设一棵二叉树的结点结构为(LLINK, INFO, R ...

  3. 012-数据结构-树形结构-哈希树[hashtree]、字典树[trietree]、后缀树

    一.哈希树概述 1.1..其他树背景 二叉排序树,平衡二叉树,红黑树等二叉排序树.在大数据量时树高很深,我们不断向下找寻值时会比较很多次.二叉排序树自身是有顺序结构的,每个结点除最小结点和最大结点外都 ...

  4. 数据库树形结构存储方法的选择

    树形结构存储方法的选择 简单的方法跟踪多级回复构成的树形分支:parent_id 一开始的思路 使用parent_id跟踪分支 使用先找出所有节点,按照一定顺序整合成树形结构 缺陷: 在深度过深时仅用 ...

  5. 在不知道根节点的情况下生成树形结构 (采用JSONObject)

    废话不多说直接上代码 /*** * 生成树形结构 在不知道跟节点的情况下* @param list 源数据* @param nodeList 跟节点数据* @param childName 子节点名称 ...

  6. 数据结构--树形结构

    数据结构--树形结构 今天在博客上看到这样一段代码,感觉挺有意思,代码如下: 1 public class Edge {2 //Name of origin town3 public Node ori ...

  7. 树形结构与关系数据库之闭包表

    闭包表记录了树中所有节点的关系,不仅仅只是直接父子关系,它需要使用2张表,除了节点表本身之外,还需要使用1张表来存储节祖先点和后代节点之间的关系(同时增加一行节点指向自身),并且根据需要,可以增加一个 ...

  8. mysql树形结构的效率_MySQL存储树形数据优化技笔记

    1.树形结构应用场景 有时我们需要保存一些树形的数据,比如组织架构.话题讨论.知识管理.商品分类等,这些数据之间存在一种递归关系,很多开发人员想到的第一个解决方案往往是记录每个节点的父节点,例如以下的 ...

  9. JAVA定义一个树形的结构_Java自定义树形结构

    Java自定义树形结构 Java自定义树形结构 为什么80%的码农都做不了架构师?>>> 树形结构 Java package com.zyl.comm; import java.ut ...

最新文章

  1. SAP EWM 性能优化(一)
  2. python简单代码input-python基础 input()函数
  3. LeetCode 6. ZigZag Conversion
  4. Java的native关键字
  5. php xls 邮件,PHPMailer发送邮件
  6. iApp对接hybbs社区APP源码
  7. SpringMVC中静态资源的处理
  8. 计算机二级知识点速记,计算机等考《二级MS+Office高级应用》高频考点速记
  9. idea中springBoot项目修改html之类的文件后服务不自动更新
  10. fiddler限制网速
  11. pyc文件反编译成py文件
  12. Java程序员薪资分级,你想到第几级?
  13. 影音嗅探专家 v2007.1 怎么用
  14. 5款热门的远程控制软件,让你事半功倍
  15. 论文翻译1-PARSEC-Streaming 360-Degree Videos Using Super-Resolution
  16. C语言中 编译预处理命令的作用有哪些,C语言系列——预处理命令
  17. zxing生成二维码及解析二维码
  18. 2020年A证(安全员)多少钱及A证(安全员)考试申请表
  19. zan php framework,zan框架入门(一)——协程
  20. CUDA By Example(七)——原子性

热门文章

  1. PHP5.4以上版本GBK编码下htmlspecialchars输出为空问题解决方法汇总
  2. Springboot整合RabbitMq-用心看完这一篇就够了(最新)
  3. java面向对象之封装,java面向对象之封装-Go语言中文社区
  4. 计算机临床医学自动化哪个好,大学专业难度排行前十名,临床医学位列第二
  5. 大一计算机理论考试知识点,计算机一级考试理论知识点整理.doc
  6. php表单确认密码,jQuery表单验证之密码确认实例详解
  7. datagrid只传入了一部分的数据 未显示全_软件开发面试之数据库事务篇
  8. windows安装ffmpeg
  9. 火车头采集php源码不同,防火车头采集的功能
  10. css 剪辑图片_CSS中的clip-path裁剪图片用法