PTA 5-52 两个有序链表序列的交集 (20分) (单链表)

来源:互联网 发布:手机视频点播软件 编辑:程序博客网 时间:2024/05/16 15:56
                                  5-52 两个有序链表序列的交集   (20分)

已知两个非降序链表序列S1与S2,设计函数构造出S1与S2的交集新链表S3。

输入格式:

输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用-11表示序列的结尾(-11不属于这个序列)。数字用空格间隔。

输出格式:

在一行中输出两个输入序列的交集序列,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL

输入样例:

1 2 5 -12 4 5 8 10 -1

输出样例:

   2  5

一开始用一般的做法,有2分会超时,问题出在建表里,先观察一下代码(18分):

#include <bits/stdc++.h>#define PI acos(-1)#define LL long long#define INF 0x3f3f3f3f#define SCD(a) scanf("%d",&a)#define SCDD(a,b) scanf("%d%d",&a,&b)#define SCF(a) scanf("%lf",&a)#define PTD(a) printf("%d", a);#define PTDE(a) printf("%d\n",a)#define MST(a,b) memset(a, b, sizeof(a))using namespace std;//                  PAT 5-52 两个有序链表序列的交集 (20分)const int M = 10010;int t;struct List{    int data;    List* next;};List* l1 = NULL;List* l2 = NULL;List* lans = NULL;void CreateList(List* &l, int val)  //注意这种建表过程{    if(!l){        l = new List;        l->data = val;        l->next = NULL;        return;    }    CreateList(l->next, val);}void BuildSet(List* &l1, List* &l2){    if(!l1 || !l2)        return;    if(l1->data == l2->data){   //相等 存表 两链表均下移一位        CreateList(lans, l1->data);        l1 = l1->next;        l2 = l2->next;        BuildSet(l1, l2);    }else if(l1->data < l2->data){  //小的下移        l1 = l1->next;        BuildSet(l1, l2);    }else{        l2 = l2->next;        BuildSet(l1, l2);    }}bool flag = true, success = false;void SearchList(List* &l){    if(!l)        return;    success = true;    if(flag){        PTD(l->data);        flag = false;    }else{        printf(" %d", l->data);    }    SearchList(l->next);}int main(){    int i ;    while(SCD(t)){        if(t == -1)            break;        CreateList(l1, t);;    }    while(SCD(t)){        if(t == -1)            break;        CreateList(l2, t);    }    bool flag = true;    BuildSet(l1, l2);    SearchList(lans);    if(!success)        puts("NULL");    return 0;}


在CreateList函数里每次添加结点前都要从头找到尾,为空才添加进去, 时间复杂度O(nlogn),  这时我们需要直接把结点加在表头,而不遍历整个
list, 时间复杂度降为O(n),  见AC代码:

#include <bits/stdc++.h>#define PI acos(-1)#define LL long long#define INF 0x3f3f3f3f#define SCD(a) scanf("%d",&a)#define SCDD(a,b) scanf("%d%d",&a,&b)#define SCF(a) scanf("%lf",&a)#define PTD(a) printf("%d", a);#define PTDE(a) printf("%d\n",a)#define MST(a,b) memset(a, b, sizeof(a))using namespace std;//                  PAT 5-52 两个有序链表序列的交集 (20分)const int M = 10010;int t;struct List{    int data;    List* next;};List* l1 = NULL;List* l2 = NULL;List* lans = NULL;List* temp = NULL;  //加一个中间变量void CreateList(List* &l, int val){    if(!l){        l = new List;        l->data = val;        l->next = NULL;        return;    }    temp = l;    l = new List;    l->data = val;    l->next = temp; //原先的list作为新list的next}// 注意由于顺序会反, 所以list为大到小建表void BuildSet(List* &l1, List* &l2){    if(!l1 || !l2)        return;    if(l1->data == l2->data){        CreateList(lans, l1->data);        l1 = l1->next;        l2 = l2->next;        BuildSet(l1, l2);    }else if(l1->data > l2->data){  //要改符号        l1 = l1->next;        BuildSet(l1, l2);    }else{        l2 = l2->next;        BuildSet(l1, l2);    }}bool flag = true, success = false;void SearchList(List* &l){    if(!l)        return;    success = true;    if(flag){        PTD(l->data);        flag = false;    }else{        printf(" %d", l->data);    }    SearchList(l->next);}int main(){    int i ;    while(SCD(t)){        if(t == -1)            break;        CreateList(l1, t);    }    while(SCD(t)){        if(t == -1)            break;        CreateList(l2, t);    }    BuildSet(l1, l2);    bool flag = true;    SearchList(lans);    if(!success)        puts("NULL");    return 0;}