二叉树(12)----查找两个节点最低祖先节点(或最近公共父节点等),递归和非递归

1、二叉树定义:

typedef struct BTreeNodeElement_t_ {
    void *data;
} BTreeNodeElement_t;

typedef struct BTreeNode_t_ {
    BTreeNodeElement_t     *m_pElemt;
    struct BTreeNode_t_    *m_pLeft;
    struct BTreeNode_t_    *m_pRight;
} BTreeNode_t;

2、查找二叉树中两个节点的最低祖先节点(或最近公共父节点等)

最低祖先节点就是从根节点遍历到给定节点时的最后一个相同节点

例如:

A

B                                            C

D                        E                     F                                G

H            I            J            K        L        M                        N    O

如上图,H和J的最低祖先节点是B。

因为从根节点A到H的链路为:   A     B    D   H

从根节点A到J的链路为:   A   B    E   J

查看链路节点可知,B是最后一个相同节点,也就是所谓的最近公共父节点或者说最低祖先节点。

(1)递归方式

如果给定pRoot是NULL,即空树,则返回的公共节点自然就是NULL;

如果给定pRoot与两个节点中任何一个相同,说明,pRoot在就是所要找的两个节点之一,则直接返回pRoot,表明在当前链路中找到至少一个节点;

如果给定pRoot不是两个节点中任何一个,则说明,需要在pRoot的左右子树中重新查找,此时有三种情况:两个节点都在左子树上;两个节点都在右子树上;一个在左子树,一个在右子树上;具体来说,就是:

情况一:如果左子树查找出的公共节点是NULL,则表明从左子树根节点开始到左子树的所有叶子节点等所有节点中,没有找到两个节点中的任何一个,这就说明,这两个节点不在左子树上,不在左子树,则必定在右子树上;

情况二:如果右子树查找的公共节点是NULL,说明在右子树中无法找到任何一个节点,则两个节点必定在左子树上;

情况三: 如果左右子树查找的公共节点都不是NULL,说明左右子树中各包含一个节点,则当前节点pRoot就是最低公共节点,返回就可以了。

三种情况是互斥的, 只能是其中之一。

BTreeNode_t *GetLastCommonParent( BTreeNode_t *pRoot, BTreeNode_t *pNode1, BTreeNode_t *pNode2){
    if( pRoot == NULL ) //说明是空树,不用查找了,也就找不到对应节点,则返回NULL
        return  NULL;

    if( pRoot == pNode1 || pRoot == pNode2 )//说明在当前子树的根节点上找到两个节点之一
        return pRoot;

    BTreeNode_t   *pLeft = GetLastCommonParent( pRoot->m_pLeft, pNode1, pNode2);  //左子树中的查找两个节点并返回查找结果
    BTreeNode_t   *pRight = GetLastCommonParent( pRoot->m_pRight, pNode1, pNode2);//右子树中查找两个节点并返回查找结果

    if( pLeft == NULL )//如果在左子树中没有找到,则断定两个节点都在右子树中,可以返回右子树中查询结果;否则,需要结合左右子树查询结果共同断定
        return pRight;
    if ( pRight == NULL )//如果在右子树中没有找到,则断定两个节点都在左子树中,可以返回左子树中查询结果;否则,需要结合左右子树查询结果共同断定
        return pLeft;

    return pRoot;//如果在左右子树中都找两个节点之一,则pRoot就是最低公共祖先节点,返回即可。
}

(2)非递归方式:

时间: 2024-10-26 12:46:16

二叉树(12)----查找两个节点最低祖先节点(或最近公共父节点等),递归和非递归的相关文章

腾讯笔试题:满二叉排序树,任给3个子节点,找他们最大的公共父节点

腾讯笔试题出现了和这个类似的题目,没做出来,现在来好好解决这个问题吧,先从基本的开始. 先吐槽一下:感觉算法设计什么的,真的超级难,也许是我头脑太笨,转不过弯来吧,呵呵. 题目是这样的:一棵满二叉排序树,有K层,节点的值依次为 1~2k-1.现在告诉你树的高度是4层,给定你3个节点,比如9,11, 13,那么最大的公共父节点是12. 现在想起来这题我已经想出来一半了呀,但是大概人在紧张的时候大脑会思维短路,跳不出原有的思维陷阱.想法是这样的: 1. 首先是从根节点开始,如果给的三个叶节点的值其中

LCA-最小公共父节点

有一个普通二叉树,AB分别为两个子节点,求AB最近(深度最大)的公共父节点. 此题仍然是一个老题,有着多种解决方法,本文针对其中三种方法来进行分析总结. 这三种方法分别是:递归法,tarjan离线算法,RMQ在线算法. 递归法 递归法比较直观简单,思路如下: 首先判定当前节点root是否是A节点或者B节点,若是的话直接返回该节点 若不是,分别对root节点的左右子树进行递归查找最小公共父节点,若左右子树都返回了节点,那么表示当前节点就是最小公共父节点,若只有其中一个子树返回了结果,那么就返回该结

查找二叉树两节点的最近公共父节点

1 //查找一棵树中最近公共父节点 2 public class LCA { 3 static boolean flag[] = new boolean[2];; 4 5 public static TreeNode findLowestCommonAncestor(TreeNode head, TreeNode first, TreeNode second){ 6 travel(head, first, second); 7 if(flag[0] == true && flag[1] =

二叉树中两个节点的最近公共父节点

这是京东周六的笔试题目   当时不在状态,现在想来肯定是笔试就被刷掉了,权当做个纪念吧.  这个问题可以分为三种情况来考虑: 情况一:root未知,但是每个节点都有parent指针此时可以分别从两个节点开始,沿着parent指针走向根节点,得到两个链表,然后求两个链表的第一个公共节点,这个方法很简单,不需要详细解释的. 情况二:节点只有左.右指针,没有parent指针,root已知思路:有两种情况,一是要找的这两个节点(a, b),在要遍历的节点(root)的两侧,那么这个节点就是这两个节点的最

笔试算法题(24):找出出现次数超过一半的元素 & 二叉树最近公共父节点

出题:数组中有一个数字出现的次数超过了数组长度的一半,请找出这个数字: 分析: 解法1:首先对数组进行排序,时间复杂度为O(NlogN),由于有一个数字出现次数超过了数组的一半,所以如果二分数组的话,划分元素肯定就是这个数字: 解法2:首先创建1/2数组大小的Hash Table(哈希表可以替代排序时间,由于一个数字出现超过了数组的一半,所以不同元素个数肯定不大于数组的一半),空间复杂度O(N),顺序扫描映射数 组元素到Hash Table中并计数,最后顺序扫描Hash Table,计数超过数组

二叉树---最近公共父节点(LCA)

题目: 给定一棵二叉树,找到两个节点的最近公共父节点(LCA). 最近公共祖先是两个节点的公共的祖先节点且具有最大深度. 4 / 3 7 / 5 6 LCA(3, 5) = 4 LCA(5, 6) = 7 LCA(6, 7) = 7 Java代码: public TreeNode lowestCommonAncestor(TreeNode root, TreeNode A, TreeNode B) { // write your code here if(root == null||root =

二叉树递归与非递归遍历,最近公共父节点算法

#include <iostream> #include <stack> using namespace std; #define MAX 100 //字符串最大长度 typedef struct Node //二叉树结点 { char data; Node *lchild,*rchild; } *Btree; void createBT(Btree &t); //先序构造二叉树 void preorder(Btree &t); //二叉树递归先序遍历 void i

二分查找算法(递归与非递归两种方式)

首先说说二分查找法. 二分查找法是对一组有序的数字中进行查找,传递相应的数据,进行比较查找到与原数据相同的数据,查找到了返回1,失败返回对应的数组下标. 采用非递归方式完成二分查找法.java代码如下所示. /* * 非递归二分查找算法 * 参数:整型数组,需要比较的数. */ public static int binarySearch(Integer[]srcArray,int des){ //第一个位置. int low=0; //最高位置.数组长度-1,因为下标是从0开始的. int h

二叉树最近公共父节点

在二叉树中找最近公共父节点.分为两种情况,一种是有父指针,一种没有父指针. 1.有父指针 这种情况比较简单,计算两个结点的深度,再把深度大的向上移,移到同一深度.在同时向上移动,直到两个结点相同,这样便找到了父节点.这个算法时间复杂度为O(N). 代码实现: #include<iostream> struct Node { int data; Node* left; Node* right; Node* parent; Node() :left(NULL), right(NULL), pare