首页 > 代码库 > 笔试算法题(28):删除乱序链表中的重复项 & 找出已经排好序的两个数组中的相同项

笔试算法题(28):删除乱序链表中的重复项 & 找出已经排好序的两个数组中的相同项

出题:给定一个乱序链表,节点值为ASCII字符,但是其中有重复项,要求去除重复项并保证不改变剩余项的原有顺序;

分析:创建一个256(2^8)大小的bool数组,初始化为false,顺序读取链表,将字母对应位置为false的重新标记为true并保留节点,将字母对 应位置为true的保持并删除节点;时间复杂度为O(N),空间复杂度为常量。注意删除节点和不删除节点的情况下,pre和cur的移动操作不相同;

解题:

 1 struct Node {
 2         char value;
 3         Node* next;
 4 };
 5 void DeleteDup(Node *head) {
 6         if(head==NULL) {
 7                 printf("\nthe list is NULL");
 8                 return;
 9         }
10 
11         Node *pre=NULL, *cur=head;
12         /**
13          * 设置一个256的bool数组记录char是否
14          * 已经出现
15          * */
16         bool haveChar[256];
17         for(int i=0;i<256;i++)
18                 haveChar[i]=false;
19         /**
20          * 如果haveChar对应为true,说明当前节点
21          * 的值已经出现过,则进行删除
22          * 如果haveChar对应为false,说明当前节点
23          * 的值第一次出现,则将其设置为true
24          * */
25         while(cur!=NULL) {
26                 /**
27                  * 注意删除节点的情况和不删除节点的情况
28                  * pre和cur的需要不同的处理
29                  * */
30                 if(!haveChar[(cur->value)-0]) {
31                         haveChar[(cur->value)-0]=true;
32                         pre=cur;
33                         cur=cur->next;
34                 }
35                 else {
36                         pre->next=cur->next;
37                         delete cur;
38                         cur=pre->next;
39                 }
40         }
41 }
42 int main() {
43         Node *a1=new Node();a1->value=http://www.mamicode.com/a;
44         Node *a2=new Node();a2->value=http://www.mamicode.com/d;
45         Node *a3=new Node();a3->value=http://www.mamicode.com/s;
46         Node *a4=new Node();a4->value=http://www.mamicode.com/d;
47 
48         a1->next=a2;a2->next=a3;
49         a3->next=a4;a4->next=NULL;
50 
51         DeleteDup(a1);
52 
53         Node *temp=a1;
54         while(temp!=NULL) {
55                 printf("\n%c",temp->value);
56                 temp=temp->next;
57         }
58         return 0;
59 }

 

出题:给定两个已排序的数组,要求找出共同的元素;

分析:

  • 如果两个数组大小接近,则分别使用指针first和second遍历两个序列,由于数组已经排序,所以遍历过的元素不会再次访问,所以时间复杂度为O(M+N);
  • 如果两个数组大小差距较大,则在针对小数组中的每个元素在大数组中使用二分查找(每处理一个元素之后,大数组的范围都可以调整到上一个元素的后面),时间复杂度为O(NlogM),N足够小(M>N^2);

解题:

 1 /**
 2  * 时间复杂度O(M+N)
 3  * */
 4 void FindCommonInt1(int *first, int fl, int *second, int sl) {
 5         int ft=0, st=0;
 6         while (ft<fl && st<sl) {
 7                 if(first[ft]>second[st]) {
 8                         st++;
 9                 } else if(first[ft]<second[st]) {
10                         ft++;
11                 } else {
12                         printf("\n%d",first[ft]);
13                         ft++;st++;
14                 }
15         }
16 }
17 /**
18  * 时间复杂度小于O(NlogM),其中M不断变小
19  * */
20 void FindCommonInt2(int *first, int fl, int *second, int sl) {
21         int start=0, end=fl-1;
22         int s,e,m;
23         for(int i=0;i<sl;i++) {
24                 s=start;e=end;
25                 while(s<=e) {
26                         m=(s+e)/2;
27                         if(first[m]>second[i]) {
28                                 e=m-1;
29                         } else if(first[m]<second[i]) {
30                                 s=m+1;
31                         } else {
32                                 printf("\n%d",first[m]);
33                                 start=m+1;
34                                 break;
35                         }
36                 }
37         }
38 }
39 int main() {
40         int first[]={1,2,3,4,5,6,10,11,12};
41         int second[]={1,4,9,10};
42         FindCommonInt2(first, 9, second, 4);
43         return 0;
44 }