其他分享
首页 > 其他分享> > 1151 LCA in a Binary Tree (30 分)

1151 LCA in a Binary Tree (30 分)

作者:互联网

 

首先是鬼鬼珊的闲聊一分钟

今天给大家扯一点什么呢?好吧,最近的论文看得我想哭,最悲伤的事是看不懂呀,尤其是国外研究的论文,一个句子长到我还要进行英文的长难句解析才勉强搞得清楚其中的深刻含义,导致我每天都想躺尸。说起来还有一件事值得一提,很久之前和朋友聊天,说起恋爱这个事,她以一个过来人的经验告诉我,在恋爱中尽量不要作,不要乱发脾气。因此,我为了促进自我良好的恋爱发展进行了深刻的调研,调研平台为知乎,哈哈哈,比如,男生喜欢什么样性格的女孩子,从上面的回答进行了认真自我反思,以尽量避免。这样看起来我还比较机智,仔细想想我可真是个魔鬼,哈哈哈。突然还有一句想说,就是这个富文本编辑器可真的太好用了吧,之前一直用的是Markdown编辑器,哇,今天的体验真的太不一样了。

好了,言归正传

The lowest common ancestor (LCA) of two nodes U and V in a tree is the deepest node that has both U and V as descendants.

Given any two nodes in a binary tree, you are supposed to find their LCA.

Input Specification:

Each input file contains one test case. For each case, the first line gives two positive integers: M (≤ 1,000), the number of pairs of nodes to be tested; and N (≤ 10,000), the number of keys in the binary tree, respectively. In each of the following two lines, N distinct integers are given as the inorder and preorder traversal sequences of the binary tree, respectively. It is guaranteed that the binary tree can be uniquely determined by the input sequences. Then M lines follow, each contains a pair of integer keys U and V. All the keys are in the range of int.

Output Specification:

For each given pair of U and V, print in a line LCA of U and V is A. if the LCA is found and A is the key. But if A is one of U and V, print X is an ancestor of Y. where X is A and Y is the other node. If U or V is not found in the binary tree, print in a line ERROR: U is not found. or ERROR: V is not found. or ERROR: U and V are not found..

Sample Input:

6 8
7 2 3 4 6 5 1 8
5 3 7 2 6 4 8 1
2 6
8 1
7 9
12 -3
0 8
99 99

Sample Output:

LCA of 2 and 6 is 3.
8 is an ancestor of 1.
ERROR: 9 is not found.
ERROR: 12 and -3 are not found.
ERROR: 0 is not found.
ERROR: 99 and 99 are not found.

 

 题目含义

在一棵二叉树中,找出两个节点的最小祖先,输入为二叉树访问的中序和先序,需要进行检测的节点u和v,如果其中有一个节点不在这棵树中,就输出这个节点找不到,两个节点都不在树中,就输出两个节点都找不到。如果u和v都在二叉树中,分两种情况,第一种为其中一个节点是另一个节点的祖先节点,第二种两个节点的共同最小祖先节点是第三个节点。对于不同的情况进行输出即可。

 思路(仅是鬼鬼珊个人思路,其他更好的idea欢迎交流-_-)

如图所示,展示了两种情况

 

                                                                              图一:找3和4的祖先 

 

                                                                    图2:找4和8的共同祖先 

  根据二叉树的访问中序和先序构建二叉树

就以这个题为例,

7 2 3 4 6 5 1 8   二叉树访问中序
5 3 7 2 6 4 8 1   二叉树访问先序

 首先,先序的第一个节点肯定就是整棵树的根节点5,root=0,到中序去找到5这个节点的索引值5(下标从0开始),就可以知道左子树有5个节点,右子树有2个节点。左子树的根节点就可以找到root+1,将这个节点的父节点设置为root,右子树的根节点为root+(左子树的个数)+1,也将这个节点的根节点设置为root,然后递归处理左子树和右子树,直到没有元素时跳出递归。图解如下图所示:

 贴代码啦

#include <iostream>
#include<bits/stdc++.h>
#define MaxSize 10001
using namespace std;
struct Node{
    int value;    //节点的值
    int parent;    //父节点的索引值
    int level;   //存放节点所在的层次
};
int M,N;
int inOrder[MaxSize];
Node preOrder[MaxSize];
//构造二叉树
void Conduct_Tree(int left,int right,int root){
     int k,i;
     int total=right-left+1;
     if(total<=0){return;}   //没有元素,跳出递归
     for(i=left;i<=right;i++){
        if(inOrder[i]==preOrder[root].value){
            k=i-left;    //左子树有多少个元素
            break;
        }
     }
     if(k>0){
         preOrder[root+1].parent=root;   //设置左子树的根节点的父节点
         preOrder[root+1].level=preOrder[root].level+1;   //设置右子树的根节点所在的level
     }
     if(total-k-1>0){
         preOrder[root+k+1].parent=root;
         preOrder[root+k+1].level=preOrder[root].level+1;
     }
     Conduct_Tree(left,i-1,root+1);     //递归处理左子树
     Conduct_Tree(i+1,right,root+k+1);   //递归处理右子树
}
void Process(int u,int v){
   bool f1=false,f2=false;
   int index1,index2;
   int temp;
   for(int i=0;i<N;i++){    //找出这棵二叉树中是否有处理的这两个节点值(输入的两个节点是一模一样的时候要注意一下)
      if(preOrder[i].value==u){
        index1=i;
        f1=true;
      }
      if(preOrder[i].value==v){
        index2=i;
        f2=true;
      }
      if(f1&&f2){
        break;
      }
   }
   if(f1&&f2){
      if(preOrder[index1].level>preOrder[index2].level){   //先判断谁的层次要高一些,就移动谁,移到同一个level
        temp=preOrder[index1].parent;
        while(preOrder[temp].level>preOrder[index2].level){  
            temp=preOrder[temp].parent;
        }
        if(preOrder[temp].value==preOrder[index2].value){   //移到一个level之后,看是否其中一个节点是另一个节点的祖先节点
            cout<<v<<" is an ancestor of "<<u<<"."<<endl;
        }
        else{
            while(preOrder[temp].value!=preOrder[index2].value){   //移到同一level之后,将两个节点继续往上走,知道共同的祖先
                temp=preOrder[temp].parent; 
                index2=preOrder[index2].parent;
            }
            cout<<"LCA of "<<u<<" and "<<v<<" is "<<preOrder[temp].value<<"."<<endl;
        }
      }
      else if(preOrder[index1].level==preOrder[index2].level){
        if(preOrder[index1].value==preOrder[index2].value){
            cout<<u<<" is an ancestor of "<<v<<"."<<endl;
        }
        else{
                while(preOrder[index1].value!=preOrder[index2].value){
                index1=preOrder[index1].parent;
                index2=preOrder[index2].parent;
                }
                cout<<"LCA of "<<u<<" and "<<v<<" is "<<preOrder[index1].value<<"."<<endl;
        }
      }
      else{
        temp=preOrder[index2].parent;
        while(preOrder[temp].level>preOrder[index1].level){
            temp=preOrder[temp].parent;
        }
        if(preOrder[temp].value==preOrder[index1].value){
            cout<<u<<" is an ancestor of "<<v<<"."<<endl;
        }
        else{
            while(preOrder[temp].value!=preOrder[index1].value){
                temp=preOrder[temp].parent;
                index1=preOrder[index1].parent;
            }
            cout<<"LCA of "<<u<<" and "<<v<<" is "<<preOrder[temp].value<<"."<<endl;
        }
      }
   }
   else if(!f1&&f2){
       cout<<"ERROR: "<<u<<" is not found."<<endl;
   }
   else if(f1&&!f2){
       cout<<"ERROR: "<<v<<" is not found."<<endl;
   }
   else{
      cout<<"ERROR: "<<u<<" and "<<v<<" are not found."<<endl;
   }
}

int main()
{
    int u,v;
    cin>>M>>N;
    for(int i=0;i<N;i++){
       cin>>inOrder[i];
    }
    for(int i=0;i<N;i++){
        cin>>preOrder[i].value;
    }
    preOrder[0].parent=-1;
    preOrder[0].level=1;
    Conduct_Tree(0,N-1,0);
    /**
    for(int i=0;i<N;i++){
        cout<<preOrder[i].value<<"   "<<preOrder[i].parent<<"   "<<preOrder[i].level<<endl;
    }**/
    for(int i=1;i<=M;i++){
        cin>>u>>v;
        Process(u,v);
    }
    return 0;
}

  运行结果

标签:Binary,preOrder,int,30,1151,二叉树,level,root,节点
来源: https://blog.csdn.net/qq_41658889/article/details/96476217