1. 单向循环链表,从头开始报数,报道m或其倍数时,出列,按照出列的先后顺序从新组织单链表
函数原型为: void convert(Node**head,int m);
解析:约瑟夫环的形式。head为二级指针,是重新组织后的循环单链表的表头。
1 void KickFromRing(RingNodePtr pHead, int m) 2 { 3 RingNodePtr pCurr, pPrev; 4 int i = 1; // 计数 5 pCurr = pPrev = pHead; 6 while(pCurr != NULL) 7 { 8 if (i == m) 9 { 10 // 踢出环 11 printf("\n%d", pCurr->pos); // 显示出圈循序 12 pPrev->next = pCurr->next; 13 free(pCurr); 14 pCurr = pPrev->next; 15 i = 1; 16 } 17 pPrev = pCurr; 18 pCurr = pCurr->next; 19 if (pPrev == pCurr) 20 { 21 // 最后一个 22 printf("\n%d", pCurr->pos); // 显示出圈循序 23 free(pCurr); 24 break; 25 } 26 i++; 27 } 28 }
2. 海量数据Top100
a.一天的优酷视频播放量约1亿,视频总数约有100w。ID号是一个大小为20字节的字符串。如何求出当天播放视频的Top100
可抽象为一个大文件,每行一个ID号,代表被播放的视频id。机器的内存不超过1G,如何抽取TOP100.先写思路,然后写程序。
b.同样一个月的视频播放量约100亿。求出当月的视频播放top100,每台机器的内存不超过1G.描述所有可能的解决方案。
解析:海量数据的处理。无法一次性装入内存,可先hash之分为多个文件处理,堆或者Trie树统计次数,求出每个文件中的Top 100。归并之求出总的top 100
对于第二问:还可以hadoop mapReduce处理之。
首先统计每个视频被观看次数,得到<id, cnt>键值对,其中id为视频id,cnt为视频被观看次数。
以cnt作为关键字建立最小堆。遍历所有键值对,若堆的size小于100,则将键值对直接插入堆,否则比较键值对和堆顶元素大小,若cnt大于堆顶元素的cnt,则弹 出堆顶元素并将键值对插入堆。
对于第一问,由于id个数较少,统计部分可直接使用stl的map容器。
对于第二问,由于id个数太大,直接hash内存不够,需要map&reduce。
3. 1-n中找缺失的数字,有n-1个数字,每一个都位于1-n之间,但是之中缺失了一个数字,要求找出这个缺失的数字,线性时间复杂度
解析:异或。原理:相同的数异或为0,0与其他数异或结果为该数。