已知两个非降序链表序列S1与S2,设计函数构造出S1与S2的交集新链表S3。
输入格式:
输入分两行,分别在每行给出由若干个正整数构成的非降序序列,用−1表示序列的结尾(−1不属于这个序列)。数字用空格间隔。
输出格式:
在一行中输出两个输入序列的交集序列,数字间用空格分开,结尾不能有多余空格;若新链表为空,输出NULL。
输入样例:
1 2 5 -1
2 4 5 8 10 -1
输出样例:
2 5
注:题目本身似乎有个 bug,虽然题目说输入的是非降序序列,但奈何本人是个萌新,其他算法运用还不熟练,最初在查找算法中的时间复杂度是 O(n^2),但是这样一来会超时。
后来还尝试了用单向加头有序链表,但是创建链表的耗时略长,最后一个测试点再次超时。。。/(ㄒoㄒ)/~~
莫得办法,只能假设输入的数据是升序来做,结果还真是升序。。。
棒极了!!
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct Node *Next;
} *link;
link createLink() // 向结尾处添加结点,创建单向加头链表
{
link head, last, p;
int x;
head = (link)malloc(sizeof(struct Node));
last = head;
while( scanf("%d", &x) != EOF && x != -1 )
{
p = (link)malloc(sizeof(struct Node));
p->Next = NULL;
p->data = x;
last->Next = p;
last = p;
}
return head;
}
link Find(link p, link q) // 寻找具有相同 data 的结点
{
link head, last, t; // 创建一个新的头和尾巴,t 用于删除空的头结点
/* 因为头结点为空,所以从下一个结点开始 */
p = p->Next;
q = q->Next;
head = last = (link)malloc(sizeof(struct Node));
last->Next = NULL;
while( p )
{
while( q )
{
if( p->data < q->data ) // 如果p结点的值小于q,p向后移
{
break;
// 因为第一层循环每次执行都会让p后移,所以直接退出第二层循环
}
else if( p->data == q->data ) // 如果结点值相同,加入尾部
{
link temp = (link)malloc(sizeof(struct Node));
temp->Next = NULL;
temp->data = p->data;
last->Next = temp;
last = temp;
q = q->Next;
break;
}
else // 如果p结点的值大于q,q向后移
{
q = q->Next;
}
}
p = p->Next; // p向后移
if( q==NULL || p==NULL ) break; // 任何一个链表指针为空即结束
}
last->Next = NULL;
/* 删除头部空结点,头结点后移 */
t = head;
head = head->Next;
free(t);
return head;
}
void printLink(link p) // 输出链表值
{
if(p == NULL)
{
printf("NULL");
return ;
}
while(p->Next) // 如果p的下一个结点不为空,即下个结点不是结尾空结点
{
printf("%d ", p->data);
p = p->Next;
}
printf("%d", p->data);
}
int main()
{
link p, q, result;
p = createLink();
q = createLink();
result = Find(p, q);
printLink(result);
return 0;
}
成功通过所有测试点!
当然,如果不使用第二个链表,直接在输入第二个链表数据的同时直接处理,速度会更快,最后一个测试点从 300ms 变为 10ms。
以下代码的 main 函数对有代码强迫症者可能不太友好,慎看!!
#include <stdio.h>
#include <stdlib.h>
typedef struct Node{
int data;
struct Node *Next;
} *link;
link createLink()
{
link head, last, p;
int x;
head = (link)malloc(sizeof(struct Node));
last = head;
while( scanf("%d", &x) != EOF && x != -1 )
{
p = (link)malloc(sizeof(struct Node));
p->Next = NULL;
p->data = x;
last->Next = p;
last = p;
}
return head;
}
/* Find 函数被去掉了,具体代码写在了main函数里头 */
void printLink(link p)
{
if(p == NULL)
{
printf("NULL");
return ;
}
while(p->Next)
{
printf("%d ", p->data);
p = p->Next;
}
printf("%d", p->data);
}
int main()
{
link p, q, head_r, last_r, t; // 创建新的头结点和尾结点
int x;
head_r = (link)malloc(sizeof(struct Node));
last_r = head_r;
p = createLink();
p = p->Next;
/* 输入的同时直接处理 */
scanf("%d", &x);
while( x != -1 && p ) // 只要输入的值不为 -1,且p所指结点不为空
{
if( x < p->data )
{
scanf("%d", &x);
}
else if( x == p->data )
{
q = (link)malloc(sizeof(struct Node));
q->data = x;
q->Next = NULL;
last_r->Next = q;
last_r = q;
p = p->Next;
scanf("%d", &x);
}
else
{
p = p->Next;
}
}
last_r->Next = NULL;
t = head_r;
head_r = head_r->Next;
free(t);
printLink(head_r);
return 0;
}
如果各位大神有更好的方法,欢迎指点本萌新!!!