#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int val;
struct Node* next;
} Node, *List;
List add(List head, int val) {
List p = (List)malloc(sizeof(Node));
p->val = val;
p->next = NULL;
head->next = p;
return p;
}
List Create() {
List dummy = (List)malloc(sizeof(Node));
dummy->next = NULL;
dummy->val = -1;
List head = dummy;
int n;
scanf("%d", &n);
while(n--) {
int num;
scanf("%d", &num);
head = add(head, num);
}
return dummy;
}
List Delete(List head, List p) {
while(head->next) {
if(head->next == p) {
head->next = head->next->next;
break;
}
head = head->next;
}
return head->next;
}
List DifferA(List dummy1, List head2) {
List p1 = dummy1->next, p2 = head2;
while(p1 && p2) {
if(p1->val < p2->val) p1 = p1->next;
else if(p2->val < p1->val) p2 = p2->next;
else {
p1 = Delete(dummy1, p1);
p2 = p2->next;
}
}
return dummy1->next;
}
void Print(List head) {
while(head->next) {
printf("%d ",head->val);
head = head->next;
}
printf("%d\n", head->val);
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
List dummy1 = Create();
List dummy2 = Create();
List head = DifferA(dummy1, dummy2->next);
Print(head);
}
return 0;
}
双指针思路:
p1 == A p2 == B
思路: 在升序的情况下,双指针同时从表头开始移动,
当p1->val < p2->val时,必定是B中没有的 仅p1向后移动到临界点(两值相等处);
当p1->val == p2->val时,把该结点删除掉 别忘了同时向后移动;
当p1->val > p2->val时,不一定,要让p2移动到后面看看有没有相等的;
因为这题要求我们不要新开辟内存,所有我只有从删除的角度入手,(本来一直想着从覆盖的角度,怎么都觉得不妥,后来上网看到一张图,改变了我的思路)
是吧,看到这个图,容易让人联想到把结点从链表中删除掉
没有这种特殊要求的话,我一般会新开一个,写起来比较方便(至少少一写del函数勒)
#include <stdio.h>
#include <stdlib.h>
typedef struct Node {
int val;
struct Node* next;
} Node, *List;
void print(List head) {
// 这题题目说了至少存在一个,可以不写
if(head == NULL) {
printf("NULL");
return;
}
while(head->next) {
printf("%d ", head->val);
head = head->next;
}
printf("%d\n", head->val);
}
List add(List head, int num) {
List p = (List)malloc(sizeof(Node));
p->val = num;
p->next = NULL;
head->next = p;
return p;
}
void create(List dummy, int n) {
while(n--) {
int num;
scanf("%d", &num);
dummy = add(dummy, num);
}
}
List del(List dummy, List p1) {
List head = dummy->next;
if(p1 == head) {
dummy->next = dummy->next->next;
free(p1);
return dummy->next;
}
for(List p = head; p; p = p->next) {
if(p->next->val == p1->val) {
p->next = p->next->next;
// 这个时候p->next已经不是你之前那个p->next
// 别混淆 => 写free(p->next)有问题 不如写下面的方便保险
free(p1);
return p->next;
}
}
}
void DifferA(List dummy, List p2) {
// p1 == A p2 == B
// 思路: 在升序的情况下,双指针同时从表头开始移动,
// 当p1->val < p2->val时,必定是B中没有的 仅p1向后移动到临界点(两值相等处);
// 当p1->val == p2->val时,把该结点删除掉 别忘了同时向后移动;
// 当p1->val > p2->val时,不一定,要让p2移动到后面看看有没有相等的;
List p1 = dummy->next;
while(p1 && p2) {
if(p1->val < p2->val) {
p1 = p1->next;
}else if(p1->val > p2->val) {
p2 = p2->next;
}else {
p1 = del(dummy, p1);
p2 = p2->next;
}
}
}
int main() {
int T;
scanf("%d", &T);
while(T--) {
List dummy1 = (List)malloc(sizeof(Node));
List dummy2 = (List)malloc(sizeof(Node));
dummy1->next = NULL;
dummy2->next = NULL;
int n1, n2;
scanf("%d", &n1);
create(dummy1, n1);
scanf("%d", &n2);
create(dummy2, n2);
DifferA(dummy1, dummy2->next);
print(dummy1->next);
}
return 0;
}