【数据结构1800题 (陈守孔) 第2章】线性表 算法设计题全解
【2.5】
【题目大意】去掉链表中绝对值重复过的数字(只保留第一个)
【解法】删除的时候用当前枚举到的节点的前一个节点,这样的话能够方便删除。用数组来判重。
【代码】
int flag[10000+10]; void quchong(LNode *L){ LNode *p = L; while (p->next!=NULL){ int t = p->next->data; if (t<0) t = -t; if (flag[t]==0){ flag[t] = 1; p = p->next; }else{ LNode *temp = p->next; p->next = temp->next; free(temp); } } }
【2.6】
【题目大意】让你把两个有序链表合并成一个有序链表
【做法】就按照归并排序的思路合并就ojbk了,合并的时候把合并后的结果接在第一个链表的头结点后面就好!
【代码】
//合并之后,放到第一个链表里面 void _merge(LNode *h1,LNode *h2){ LNode *p1 = h1->next;LNode *p2 = h2->next,*t; h1->next = NULL; t = h1; while (p1!=NULL && p2!=NULL){ if (p1->data<p2->data){ t->next = p1; t = p1; p1 = p1->next; }else{ t->next = p2; t = p2; p2 = p2->next; } } while (p1!=NULL) { t->next = p1;t = p1; p1=p1->next; } while (p2!=NULL){ t->next = p2;t = p2; p2 = p2->next; } }
【2.7】
【题目大意】一个升序一个逆序的链表,让你合并成一个有序的单链表。
【做法】把逆序的那个原地倒置就好
//先把第二个链表原地倒置 然后当成2.6的合并做就好 void _merge(LNode *h1,LNode *h2){ LNode *p = h2->next; h2->next = NULL; while (p){ LNode * temp = p->next; p->next = h2->next; h2->next = p; p = temp; } LNode *p1 = h1->next;LNode *p2 = h2->next,*t; h1->next = NULL; t = h1; while (p1!=NULL && p2!=NULL){ if (p1->data<p2->data){ t->next = p1; t = p1; p1 = p1->next; }else{ t->next = p2; t = p2; p2 = p2->next; } } while (p1!=NULL) { t->next = p1;t = p1; p1=p1->next; } while (p2!=NULL){ t->next = p2;t = p2; p2 = p2->next; } }
【2.8】同【2.6】代码
【2.9】
【题目大意】
无头结点的单链表两个
两个都是有序的
让你把这两个单链表合并成一个链表。
要求不能破坏第二个链表的结构
【做法】
在做归并的时候,如果第一个等于第二个,那么就跳过第二个链表遍历到的元素,这样第一个链表上有的元素,第二个链表里对应的就不会管他了。
无头结点不好直接在h1的基础上添加新的元素,所以自己另外创建一个无头结点的链表.一个一个累加上去就好。
【代码】
//这里必须要用二重指针,因为我们要改变第一个链表的指向(我们新创的一个链表) //main函数里调用_merge(&h1,h2)即可(h2不用变) void _merge(LNode **h1,LNode *h2){ LNode *p1 = *h1;LNode *p2 = h2,*h3; h3 = newnode();//不好直接接在第一个链表上,所以新创建一个 LNode *t = newnode(); t = h3; while (p1!=NULL && p2!=NULL){ if (p1->data<p2->data){ LNode *temp = newnode(); //不能破坏原始链表,所以只能自己创了 temp->data = p1->data; t->next = temp; t = temp; p1 = p1->next; }else if (p1->data>p2->data){ LNode *temp = newnode(); temp->data = p2->data; t->next = temp; t = temp; p2 = p2->next; }else if (p1->data==p2->data){ //如果两个链表中有,那么只要第一个链表中的 p2 = p2->next; } } if (p1==NULL) p1 = p2; //这样写比较简洁 while (p1!=NULL) { LNode *temp = newnode(); temp->data = p1->data; t->next = temp;t = temp; p1=p1->next; } *h1 = h3->next;//让h1再指向h3 }
【2.10】和【2.9的代码一样】只不过变成带头结点的了。遍历到两个链表的p和q的时候,如果p->data==q->data,则跳过其中一个就好了。
因为是集合,所以只会重复一次。
【2.11】
【题目大意】
求两个集合的交集(在两个链表里递增排列),
【做法】
也没说带不带头结点。。。就当做是有头结点吧。放在A链表中,这个简单,重构下A链表就好。
在归并的时候,如果p和q节点的节点值相同,就加到A链表的后面就好
【代码】
void _merge(LNode *h1,LNode *h2){ LNode *p1 = h1->next;LNode *p2 = h2->next,*t; h1->next = NULL; t = h1; while (p1!=NULL && p2!=NULL){ if (p1->data<p2->data){ p1 = p1->next; }else if (p1->data>p2->data){ p2 = p2->next; }else if (p1->data==p2->data){ //如果两个链表中有,任取一个放在newA链表后面 t->next = p1; t = p1; p1 = p1->next; } } }
【2.12】和【2.11】一样的。
【2.13】也一样。。
【2.14】
题目大意:给你三个递增链表A,B,C让你求A∪(B∩C),时间复杂度要求为O(|A|+|B|+|C|)