出题:给定一个乱序链表,节点值为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(" the 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='a'; 44 Node *a2=new Node();a2->value='d'; 45 Node *a3=new Node();a3->value='s'; 46 Node *a4=new Node();a4->value='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(" %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(" %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(" %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 }