精华内容
下载资源
问答
  • 给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数...
    给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数原型:
    
    C++函数原型:
    strucy TreeNode{
         TreeNode* left;   //指向左子树
         TreeNode* right;   //指向右子树
         TreeNode* father;   //指向父亲节点
    };
    TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second){
    }


    思路一:我们首先找到两个节点的高度差,然后从较靠近根结点的一层开始向上找,若父节点为同一节点则该节点为解。
    intgetHeight(TreeNode *node) {
        intheight = 0;
        while(node) {
            height++;
            node = node->parent;
        }
        returnheight;
    }
     
    TreeNode* LowestCommonAncestor(TreeNode* first,TreeNode* second) {
        intheight1 = getHeight(first), height2 = getHeight(second), diff = height1 - height2;
        if(diff < 0) {
            diff = -diff;
            while(diff--) {
                 second = second->parent;
            }
        } else{
            while(diff--) {
                first = first->parent;
            }
        }
        while(first != second) {
            first = first->parent;
            second = second->parent;
        }
        returnfirst;
    }
    

    思路二:若允许浪费空间,那么可以用两个Stack来存储从first和second到根结点的各个节点,然后出栈时比较地址是否一致,最后一个地址一致的节点为解。

    两种方法最坏时间复杂度均为O(n)。

    展开全文
  • LCA-最小公共父节点

    千次阅读 2015-07-19 10:37:22
    有一个普通二叉树,AB分别为两个子节点,求AB最近(深度最浅)的公共父节点。 此题仍然是一个老题,有着多种解决方法,本文针对其中三种方法来进行分析总结。 这三种方法分别是:递归法,tarjan离线算法,RMQ在线...

    有一个普通二叉树,AB分别为两个子节点,求AB最近(深度最大)的公共父节点。
    此题仍然是一个老题,有着多种解决方法,本文针对其中三种方法来进行分析总结。

    这三种方法分别是:递归法,tarjan离线算法,RMQ在线算法。


    递归法

    递归法比较直观简单,思路如下:

    • 首先判定当前节点root是否是A节点或者B节点,若是的话直接返回该节点
    • 若不是,分别对root节点的左右子树进行递归查找最小公共父节点,若左右子树都返回了节点,那么表示当前节点就是最小公共父节点,若只有其中一个子树返回了结果,那么就返回该结果节点。

      参考代码如下:

    TreeNode* lowestCommonAncestor(TreeNode* root, TreeNode* p, TreeNode* q) {
            if(!root)
                return NULL;
    
            if(root == p || root == q)
                return root;
    
            TreeNode* left = lowestCommonAncestor(root->left,p,q);
            TreeNode* right = lowestCommonAncestor(root->right,p,q);
    
            if(left == NULL) return right;
            if(right==NULL) return left;
    
            return root;
        }

    在线算法
    如上图中我们要查找节点4,3的最小公共父节点,那么上述代码的执行过程如下

    • 判断1是否4,3节点不是,查询1的左子树和右子树
    • 1的左子树中先判断2是否4,3节点不是,查找2的左右子树
      • 2的左子树 显然返回结果4,2的右子树返回结果NULL,显然2的左右子树并没有都返回树中的节点,因此2不是4,3的最小公共父节点,因此以2位根节点的1的左子树调用方法返回的是4.
    • 1的右子树判断3节点是否是4,3节点,发现是的,直接返回3节点。
    • 1的左右子树的递归调用都返回了结果,因此1就是节点4,3的最小公共父节点。

    Tarjan离线算法

    对于该算法,常常会有一个给定的树T和一个给定的查询集合P={(u,v)},我们需要确定P中每对的最小公共祖先。
    算法为何说是离线的?因为针对所有的查询,我们都是在算法的一次执行过程中找到。

    算法思路:

    • 根节点root开始搜索,每次递归搜索所有的子树
    • 当搜索到节点u时,创建一个由u本身组成的集合,这个集合的祖先为u自己。然后递归搜索u的所有儿子节点。每个儿子节点递归完毕之后,将儿子节点所在的集合和u所在的集合合并,再把该集合的祖先设定为节点u。
    • 每个节点的所有孩子都递归完毕后,将该节点设定为已经访问过,开始遍历所有u的查询,若发现查询的另外一个节点v也是标示为访问过的话,那么节点u和v的最小公共父节点即为节点v所在集合的祖先节点。

    上述所有操作都是使用并查集高效完成的。因此时间复杂度,O(n)深度优先搜索所有节点的时间,搜索每个节点时会遍历这个节点相关的所有查询。如果总的查询个数为q,则总的复杂度为O(n+q)。

    还是上图的树,我们从节点1开始,创建集合{1},然后递归到1的第一个孩子节点2,创建集合{2},之后继续深度递归到节点4,创建集合{4},完成节点4的访问后,将4设定为已访问,集合{4}与集合{2}合并,得到{4,2},将他们的祖先设为2,然后访问节点5,创建集合{5},完成之后将集合{2,4}和{5}合并,得到{2,4,5}然后将该集合的祖先设为2,若此时(5,4)是一个查询,那么就可以得到他们的最小公共祖先为2。之后合并{1}和{2,4,5}得到{1,2,4,5},祖先为1,访问3,继续访问6,完成之后,若(6,2)是一个查询,那么其最小公共祖先为1。剩下的操作类似。

    伪代码如下(参考算法导论):

    LCA(u)
      MAKE-SET(u)
      Find-Set(u).ancestor = u
      for each child v of u in T
          LCA(u)
          Union(u,v)
          Find-Set(u).ancestor = v
      u.color= Black
      for each node v such that (u,v) belongs to P
                if v.color ==Black
                   print "The LCA of "u "and" v"is" Find-Set(v).ancestor

    RMQ在线算法

    无论是一个询问还是很多个询问,使用离线算法都是只需要做一次深度优先搜索就可以了的。所以离线算法针对一次性较多查询的话比较实惠,但是每次只来一个查询,这时候多次调用离线算法就不值当了。在线算法处理这种情况比较合适。

    之前文章里写过RMQ在线算法的原理了,这里就不加多说,本文主要介绍如何把RMQ算法和最小公共父节点问题结合起来。

    算法思路:

    LCA集合RMQ主要是通过DFS(深度优先搜索)完成。每次经过某一个点——无论是从它的父亲节点进入这个点,还是从它的儿子节点返回这个点,都按顺序记录下来,还是上面的树,DFS之后顺序为:1-2-4-2-5-2-1-3-6-3-1。那么要找到树上两个节点的最近公共祖先,无非就是找到这两个节点最后一次出现在数组中的位置所囊括的一段区间中深度最小的那个点,并且我们假定我们的树中每个父亲节点的标号都比孩子节点小,那么目标就转换为求该区间中标号最小的那个节点。

    部分代码如下:

    int ind[N];//用来存储每个节点在生成路径中最后一次出现的位置
    vector<int> road;//存储DFS路径
    void dfs(int s)
    {
        road.push_back(s);
        for(int i = 0; i < V[s].size();i++){
            dfs(V[s][i]);
            road.push_back(s);
        }
    }

    得到路径之后,那么每个节点在生成路径中最后一次出现的位置可以用如下方式得到:

    for(int i = 0; i < road.size();i++)
    {
            ind[road[i]] = i + 1;
    }

    进行上述操作之后,对于每一对查询(u,v),我们再利用RMQ区间查询的算法输入ind[u],ind[v]就能得到其最小公共父节点了。


    总结

    本文总结了三种不同求解最小公共父节点的方法,本人曾在微软面试中被问及此题,答得并不是很好,若是能在面试中答出多种方法,那么一定会有大大的加分。

    展开全文
  • 二叉树之最小公共父节点

    千次阅读 2013-10-15 20:36:35
      import java.util.LinkedList;   public class CommonFather { ... * 思路:最原始的方法,从根开始,分别寻找从根节点到每个目标节点的路径,然后比较 两条路径,找到最小的公共父节点。  *

    package com.Tree;

     

    import java.util.LinkedList;

     

    public class CommonFather {

     

      /**

       * 题目描述:给定一棵二叉树,要求找到其中任意两节点的最小公共父节点。

       * 思路:最原始的方法,从根开始,分别寻找从根节点到每个目标节点的路径,然后比较 两条路径,找到最小的公共父节点。

       * @param args

       * @author Adai

       */

      private LinkedList<TNode> path;

      private static class TNode{

         int data;

          TNode leftchild;

          TNode rightchild;

         public TNode(int da){

            this.data=da;

            this.leftchild=null;

            this.rightchild=null;

          }

       }

      private TNode root;

      public CommonFather(int[] list){

          TNode curr=null;

         for(int i=0;i<list.length;i++){

             TNode now=new TNode(list[i]);

            if(i==0){

               root=now;

                curr=root;

             }else{

                curr=root;

               while(curr!=null){

                   if(curr.data<now.data){

                      if(curr.rightchild!=null){

                          curr=curr.rightchild;

                       }else{

                          curr.rightchild=now;

                         break;

                       }

                    }else{

                      if(curr.leftchild!=null){

                          curr=curr.leftchild;

                       }else{

                          curr.leftchild=now;

                         break;

                       }

                      

                    }

                }

               

             }

          }

       }

      public static void main(String[] args) {

         // TODO Auto-generated method stub

         int[] list={5,4,6,3,7,2,8,1,9};

          CommonFather cf=new CommonFather(list);

          TNode tar=cf.FindCommonFather(cf.root, 3, 7);

          System.out.println(tar.data);

       }

      public TNode FindCommonFather(TNode root,int t1,int t2){

         if(root==nullreturn null;

         path=new LinkedList<TNode>();

          LinkedList<TNode> set=new LinkedList<TNode>();

          TNode cur=root;

         if(FindTNode(cur,t1)){

            

            while(!path.isEmpty()){

                TNode now=path.pop();

                set.push(now); 

                System.out.println(now.data);

             }

          }else{

            return null;

          }

         path.clear();

          cur=root;

          LinkedList<TNode> guest=new LinkedList<TNode>();

         if(FindTNode(cur,t2)){

             TNode cf=null;

            while(!path.isEmpty()){

                TNode now=path.pop();

                System.out.println("2:"+now.data);

                guest.push(now);

             }

          }else{

            return null;

          }

          TNode ret=null;

         while(!set.isEmpty()&&!guest.isEmpty()){

             TNode se=set.pop();

             TNode ge=guest.pop();

            if(se.equals(ge)){

                ret=se;

             }else{

               return ret;

             }

          }

         return null;

       }

      

      private boolean FindTNode(TNode nowroot,int target){

         path.push(nowroot);

         if(nowroot==null){

            path.pop();

            return false;

          }else if(nowroot.data==target){

            return true;

          }else{

            if(FindTNode(nowroot.leftchild,target)){

               return true;

             }

            if(FindTNode(nowroot.rightchild,target)){

               return true;

             }

            path.pop();

            return false;

          }

       }

    }

    展开全文
  • 二叉树中2个节点的最小公共父节点

    千次阅读 2017-01-19 15:17:03
    关于如何求二叉树2个节点的最小公共父节点,分2种情况讨论 情况1:节点有parent节点  这种情况就直接找到节点1和节点2的根节点,然后求得2个链表的长度,再求得长度差。如果说2条链子的长度差为n,那么  就长的...

    关于如何求二叉树2个节点的最小公共父节点,分2种情况讨论

    情况1:节点有parent节点

               这种情况就直接找到节点1和节点2的根节点,然后求得2个链表的长度,再求得长度差。如果说2条链子的长度差为n,那么

     就长的节点先移动n步,然后和短的节点一起移动,并且判断父节点是否相等。那么这边其实也解决了另一个问题,就是求2个链表

     的交点。

                public static Node publicNode(Node node1,Node node2){

                //接下来是求2个条链的起始点

                int length1 = getLength(node1);

                int length2 = getLength(node2);

               Node firstNode,secondNode;

                int res = 0;

                if(length1>=length2)

                res = length1 - length2;

                for(int i = 0;i<res;i++){

                firstNode = firstNode.parent;

                }

                else{

                res = length2 - length1;

                for(int i = 0;i<res;i++){

                secondNode = secondNode.parent;

                }

              // 接下来是从起始节点开始找交点

               while(firstNode.parent!=null||secondNode.parent!=null){

                          if(node1.parent==node2.parent)

                          return node1.parent;

                          else{

                             firstNode = firstNode.parent;

                             secondNode = secondNode.parent;

                          }

               }

               }

           其实会这么一个问题,就会求链表的交点和求二叉树的2个节点的最小公共父节点了。

      情况2,节点没有parent节点

      这个其实也简单,就是从根节点开始层次遍历这棵树,然后判断当前节点是否包含2个节点,如果包含就继续遍历当前节点的

      左右节点是否包含这2个节点,如果包含就继续深入。如果左右都不包含,那么当前节点就是最小公共父节点。

      public static Node getPublicNode(Node node1,Node node2){

                //获得根节点,并且对根节点进行层次遍历

                Node root = getRoot(node1);

                Deque<Node> deque = new Deque<Node>();

                deque.add(root);

                while(deque.size()!=0){

                Node node = deque.peekFirst();

                if(node.containChilds(node1,node2)){

                 //当当前节点包含2个节点,而它的左右节点都不包含2个节点,那么它就是最小公共父节点

                if(node.left!=null&&node.right!=null&&!node.right.containChilds&&!node.left.containChilds){

                 return node;

                 }

                if(node.left!=null&&node.left.containChilds(node1,node2))

                deque.add(node.left);

               if(node.right!=null&&node.right.containChilds(node1,node2))

                deque.add(node.right);

                }

               }

     }

           

    展开全文
  • /** * Definition for a binary tree node. * struct TreeNode { * int val; * TreeNode *left; * TreeNode *right; * TreeNode(int x) : val(x), left(NULL), right(NULL) {} * }; ...clas
  • 查找二叉树中x和y的最小公共父节点。 代码实现:见我的github:findxandy 二、解题思路 1)写一个查找函数 findx:查找x是否在树2root中。 2)查找 root 的左孩子是否有该结点,递归。 3)查找 root ...
  • leetcode 236 二叉树的最小共同父节点

    千次阅读 2018-12-04 12:54:05
    给定一个二叉树, 找到该树中两个指定节点的最近公共祖先。 百度百科中最近公共祖先的定义为:“对于有根树 T 的两个结点 p、q,最近公共祖先表示为一个结点 x,满足 x 是 p、q 的祖先且 x 的深度尽可能大(一个节点...
  • 给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数...
  • 给定一颗二叉树,以及其中的两个node(地址均非空),要求给出这两个node的一个公共父节点,使得这个父节点与两个节点的路径之和最小。描述你程序的最坏时间复杂度,并实现具体函数,函数输入输出请参考如下的函数...
  • 二叉树中两个节点的最近公共父节点
  • sql 获取指定节点的所有父节点或者所有子节点       获取节点的所有父节点 ;with #tmp as( select * from tb where id = 'DMA20120327036' union all select a.* from tb a, #tmp b where a....
  • 情况二:节点只有左、右指针,没有parent指针,root已知 思路:有两种情况,一是要找的这两个节点(a, b),在要遍历的节点...那么另一边返回的就是他们的最小公共父节点。 递归有两个出口,一是没有找到a或者b,则
  • 思路:有两种情况,一是要找的这两个节点(a, b),在要遍历的节点(root)的两侧,那么这个节点就是这两个节点的最近公共父节点; 二是两个节点在同一侧,则 root->left 或者 root->right 为 NULL,另一边返回a或者...
  • 寻找二叉树两个结点的最低共同父节点1.使用递归的思想(从根节点自上向下查找,优点直观易懂,缺点使用较大内存);2.使用迭代的思想(从两目标节点自下向上查找,缺点运行较长时间,改进:可以牺牲内存记录找过的节点...
  • 如图中H和F的最低公共祖先节点就是A 解法1: 遍历出所有叶节点到根节点的路径,得到 ABD ABEH ACFI ACG 可以发现要找出H和F的最低祖先节点只要找到任意一条包含F和任意一条一条H的字符串,找出最大前缀的位置即可 ...
  • 此时可以分别从两个节点开始,沿着parent指针走向根节点,得到两个链表,然后求两个链表的第一个公共节点,这个方法很简单,不需要详细解释的。 情况二:节点只有左、右指针,没有parent指针,root已知 思路:有...
  • 1、题目描述 ... 给定两个节点p = 5, q = 4,那么p和q的最小的公共祖先节点为5。 2、解题思路 可以分别使用两个数组来保存从根节点到给定的两个节点的路径值,然后再从路径中找出最后一个相...
  • 思路:当遇到一个结点是返回1,当左右子树都返回1的时候,即最小公共父节点。//二叉树的数据结构 typedef struct MyStruct { char data; struct MyStruct *leftChild; struct MyStruct *rightChild; }Node, *Tree...
  • //获取右子树中的最小节点 public Node minRightNode(Node node){//传入参数为被删除节点的右孩子Node node if(node.getLeftChild()==null){ return null; } if(node.getLeftChild().getLeftChild()==null...
  • python实现最小

    千次阅读 2019-04-17 23:21:02
    父节点值不大于子节点且根节点值最小称为最小堆,反之称为最大堆。最大堆和最小堆没有本质上的区别。如下图是一个典型的最小堆: 方法一: 从根节点(index = 0)遍历到最后一个拥有子节点的节点(index = N//2 -1...
  • 1 首先利用最小堆的这种数据结构的特点,子节点不小于父节点的特性,最小堆构建后,根节点就是最小值 2 构建最小堆:子节点中最小的和父节点互换,然后对子节点的子树递归构建最小堆 3 最小堆构建完成后,就可以...
  • 最小支配集

    千次阅读 2019-08-01 18:44:32
    最小支配集,最大独立集,最小点覆盖参考博客...最后反向贪心选择点,如果这个点没有被标记,我们就将他父亲加进点集里面标记这个点 ,父节点父节点父节点(至于为什么反...
  • 【数据结构与算法】最小堆 minheap

    万次阅读 2017-02-01 06:53:56
    最小堆的定义是,一棵完全二叉树,每一个节点都大于等于其父节点。完全二叉树是叶子都在最后一层,且尽量靠左。 实现方面可以使用链表或者数组,这里使用数组。 如果使用数组,那么下标从0开始,父节点是i,则左...
  • 最小生成树-最小权值

    千次阅读 2018-01-02 06:53:13
    两种方式 1.kruskal:归并边 存储方式:邻接表 时间复杂度:O(eloge) 适用于:稀疏网 ...SL:将边按照从小到大排序,通过判断父节点是否相同,不同可归并,归并边次数n-1 /* Kruskal:最小生成树 原理:归并边; */
  • 最小堆问题

    2015-03-28 17:16:53
    最小堆的概念:所有父节点的值小于或等于两子节点的值,并且它所有元素按完全二叉树的顺序存储方式存放在一个一维数组中。 如图: 关于堆的操作: 1.建立最小堆:将普通数组转换成堆,转换完成后,数组就...
  • 2.根元素是最小的元素,父节点小于它的两个子节点。 3.树中的元素是相对有序的。 如何实现堆的相对有序是关键。 插入元素时,插入到数组中的最后一个元素的后面,然后与该节点的父节点比较大小。如果插入的元素小于...
  • 上次用Java实现了最大堆的封装,这次就来写一下最小堆的实现吧插入函数的思路: ...另一种是当前节点的值小于父节点,那么就要将二者的值进行调换,然后记得更新当前节点为原来父节点的位置,而父节点的位
  • C++实现最大堆和最小

    千次阅读 2018-08-19 20:47:17
    堆 堆数据结构是一种数组对象,它可以被视为一颗完全二叉树结构(或者也有可能是满二叉树) 最大堆: 任一结点的关键码均大于等于它的左右孩子的关键码,其中堆顶的...左孩子节点 = 2*父节点+1 右孩子节点 = ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 106,879
精华内容 42,751
关键字:

最小父节点