1. 程式人生 > 其它 >【連結串列】找出直系親屬

【連結串列】找出直系親屬

技術標籤:機試

題目描述

如果A,B是C的父母親,則A,B是C的parent,C是A,B的child,如果A,B是C的(外)祖父,祖母,則A,B是C的grandparent,C是A,B的grandchild,如果A,B是C的(外)曾祖父,曾祖母,則A,B是C的great-grandparent,C是A,B的great-grandchild,之後再多一輩,則在關係上加一個great-。

輸入描述:

 輸入包含多組測試用例,每組用例首先包含2個整數n(0<=n<=26)和m(0<m<50), 分別表示有n個親屬關係和m個問題, 然後接下來是n行的形式如ABC的字串,表示A的父母親分別是B和C,如果A的父母親資訊不全,則用-代替,例如A-C,再然後是m行形式如FA的字串,表示詢問F和A的關係。
 

輸出描述:

 如果詢問的2個人是直系親屬,請按題目描述輸出2者的關係,如果沒有直系關係,請輸出-。
 具體含義和輸出格式參見樣例.

示例1

輸入

複製

3 2
ABC
CDE
EFG
FA
BE

輸出

複製

great-grandparent
-

題目連線:https://www.nowcoder.com/practice/2c958d09d29f46798696f15ae7c9703b?tpId=40&tqId=21453&rp=1&ru=%2Fta%2Fkaoyan&qru=%2Fta%2Fkaoyan%2Fquestion-ranking&tab=answerKey

其實本質相當於倒過來的二叉樹

比如題目中的例子

A是BC的孩子,那麼應該建立由B向A的連結串列和由C向A的連結串列,這樣的目的是從任何一個節點向下遍歷方向是唯一的,容易確定先後順序

比如我想知道G和C是不是直系親屬,那麼從G遍歷下來的路徑是GECA,這裡麵包含了C,所以G是C的爺爺(因為隔了兩代)

如果判斷G和D是不是直系親屬,從G向下遍歷是GECA,從D遍歷下來時DCA,注意,雖然有交集CA,但由於G的遍歷中不含有D,D的遍歷中不含有G,所以兩者不是直接親屬

基於以上的思想,我們可以開一個map分別記錄每一個人的指標,之後開一個vector,記錄每人向下遍歷的路徑。

之後比如想知道B和G的關係,首先根據map找到B指標,根據指標找到vector中B的遍歷路徑,查詢是否有G。如果有的話,證明B是G的前輩,按照代數輸出parent即可。

如果沒有,則反過來根據map找到G的指標,根據指標找到vector中G的遍歷路徑,查詢是否有B,如果有證明B是G的孩子,根據代數輸出child即可。

若也沒有,則為-,即不是直系親屬

總結:是一道連結串列的好題目

#include<iostream>
#include<cstdio>
#include<queue>
#include<cmath>
#include<algorithm>
#include<cstring>
#include <sstream>
#include<map>
using namespace std;
struct data{
    char id;
    data* child;
    data(char id):id(id),child(NULL){}
};
int find(vector<char> v,char text){
    for(int i=0;i<v.size();i++){
        if(v[i]==text){
            return i;
        }
    }
    return -1;
}
map<char,data*>mp;
int main(){
    int num,ques;
    cin>>num>>ques;
    mp.clear();
    for(char i='A';i<='Z';i++)
        mp[i]=NULL;
    while(num--){
        char a[3];
        cin>>a;
        data* p1=mp[a[1]];
        data* p2=mp[a[2]];
        //如果map中沒有這個人的指標位置,則需要存入map
        //如果已經有了,即p1!=NULL時,表明之前已經存入map了,不用再次儲存
        if(p1==NULL){
            p1=new data(a[1]);
            mp[a[1]]=p1;
        }
        if(p2==NULL){
            p2=new data(a[2]);
            mp[a[2]]=p2;
        }
        data* p0=mp[a[0]];
        if(p0==NULL){
            p0=new data(a[0]);
            mp[a[0]]=p0;
        }
        //如果缺少父母資訊,則不存入資料
        if(a[1]!='-')
            p1->child=p0;
        if(a[2]!='-')
            p2->child=p0;
    }
    vector<char>v[26];
    //記載每一個人的遍歷路徑,比如vector[0]表明A從上到下的遍歷路徑
    for(int i=0;i<26;i++){
        data* now=mp['A'+i];
        while(now!=NULL){
            v[i].push_back(now->id);
            now=now->child;
        }
    }
    while(ques--){
        char temp[2];
        cin>>temp;
        char s1=temp[0];
        char s2=temp[1];
        int ans=find(v[s1-'A'],s2);
        if(ans==-1){//從s1到s2找不到時,倒過來找試試,因為s1不是s2的前輩時,有可能s1是s2的後輩
            ans=find(v[s2-'A'],s1);
            if(ans==-1){//既不是前輩也不是後輩,則不是直系親屬
                cout<<"-"<<endl;
            }
            else if(ans==1)
                cout<<"child"<<endl;
            else if(ans==2)
                cout<<"grandchild"<<endl;
            else {
                for(int i=1;i<=ans-2;i++)
                    cout<<"great-";
                cout<<"grandchild"<<endl;
            }
        }
        else{
            if(ans==1)
                cout<<"parent"<<endl;
            else if(ans==2)
                cout<<"grandparent"<<endl;
            else{
                for(int i=1;i<=ans-2;i++)
                    cout<<"great-";
                cout<<"grandparent"<<endl;
            }
            
        }
    }
}