分享

腾讯面试题:有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。

pig2 发表于 2014-4-7 00:24:47 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 16 38796
有一千万条短信,有重复,以文本文件的形式保存,一行一条,有重复。
请用5分钟时间,找出重复出现最多的前10条。


已有(20)人评论

跳转到指定楼层
pig2 发表于 2014-4-7 00:24:54
本帖最后由 pig2 于 2014-4-7 10:53 编辑


分析:

常规方法是先排序,在遍历一次,找出重复最多的前10条。但是排序的算法复杂度最低为nlgn。

可以设计一个hash_table, hash_map<string, int>,依次读取一千万条短信,加载到hash_table表中,并且统计重复的次数,与此同时维护一张最多10条的短信表。

这样遍历一次就能找出最多的前10条,算法复杂度为O(n)。

实现如下:

  1. #include<iostream>
  2. #include<map>
  3. #include<iterator>
  4. #include<stdio.h>
  5. using namespace std;
  6. #define HASH __gnu_cxx
  7. #include<ext/hash_map>
  8. #define uint32_t unsigned int
  9. #define uint64_t unsigned long int
  10. struct StrHash
  11. {
  12. uint64_t operator()(const std::string& str) const
  13. {
  14. uint32_t b = 378551;
  15. uint32_t a = 63689;
  16. uint64_t hash = 0;
  17. for(size_t i = 0; i < str.size(); i++)
  18. {
  19. hash = hash * a + str[i];
  20. a = a * b;
  21. }
  22. return hash;
  23. }
  24. uint64_t operator()(const std::string& str, uint32_t field) const
  25. {
  26. uint32_t b = 378551;
  27. uint32_t a = 63689;
  28. uint64_t hash = 0;
  29. for(size_t i = 0; i < str.size(); i++)
  30. {
  31. hash = hash * a + str[i];
  32. a = a * b;
  33. }
  34. hash = (hash<<8)+field;
  35. return hash;
  36. }
  37. };
  38. struct NameNum{
  39. string name;
  40. int num;
  41. NameNum():num(0),name(""){}
  42. };
  43. int main()
  44. {
  45. HASH::hash_map< string, int, StrHash > names;
  46. HASH::hash_map< string, int, StrHash >::iterator it;
  47. NameNum namenum[10];
  48. string l = "";
  49. while(getline(cin, l))
  50. {
  51. it = names.find(l);
  52. if(it != names.end())
  53. {
  54. names[l] ++;
  55. }
  56. else
  57. {
  58. names[l] = 1;
  59. names[l] = 1;
  60. }
  61. }
  62. int i = 0;
  63. int max = 1;
  64. int min = 1;
  65. int minpos = 0;
  66. for(it = names.begin(); it != names.end(); ++ it)
  67. {
  68. if(i < 10)
  69. {
  70. namenum[i].name = it->first;
  71. namenum[i].num = it->second;
  72. if(it->second > max)
  73. max = it->second;
  74. else if(it->second < min)
  75. {
  76. min = it->second;
  77. minpos = i;
  78. }
  79. }
  80. else
  81. {
  82. if(it->second > min)
  83. {
  84. namenum[minpos].name = it->first;
  85. namenum[minpos].num = it->second;
  86. int k = 1;
  87. min = namenum[0].num;
  88. minpos = 0;
  89. while(k < 10)
  90. {
  91. if(namenum[k].num < min)
  92. {
  93. min = namenum[k].num;
  94. minpos = k;
  95. }
  96. k ++;
  97. }
  98. }
  99. }
  100. i++;
  101. }
  102. i = 0;
  103. cout << "maxlength (string,num): " << endl;
  104. while( i < 10)
  105. {
  106. cout << "(" << namenum[i].name.c_str() << "," << namenum[i].num << ")" << endl;
  107. i++;
  108. }
  109. return 0;
  110. }
复制代码


使用g++编译如下:

g++ main.cpp -o main

短信文本文件为:msg.txt

运行:./main < msg.txt

输出结果为:

maxlength (string,num):
(点点母婴坊,4)
(农机配件维修,5)
(红胜超市,6)
(龙溪大酒店,8)
(张记饺子馆,3)
(友谊旅店,3)
(明珠通讯,3)
(金源旅馆,3)
(洞庭山天然泉水,2)
(清源超市,3)


csdn

点评

想问一下,怎么保证hash key和msg是唯一配对的呢? 会不会有不同msg,具有相同hash key?  发表于 2016-7-27 15:00
很厉害  发表于 2015-6-24 03:48
回复

使用道具 举报

hochikong 发表于 2014-4-7 11:18:43
有空研究一下用 python实现一下

点评

小刚,很卡哇音  发表于 2014-4-7 11:27
回复

使用道具 举报

kevin 发表于 2014-4-7 12:22:55
应该可以用MATLAB处理的
回复

使用道具 举报

shl_gao 发表于 2014-4-7 12:46:10

点评

小伙子,你认为那  发表于 2014-4-7 12:50
回复

使用道具 举报

dearboll 发表于 2014-4-10 20:58:03
不懂C++。。。只会Java.楼主有java的实现吗?
还有,如果只用MapReduce来实现的话,运行两个Job也可以,但是会比楼主的办法麻烦很多,学习了~
回复

使用道具 举报

hochikong 发表于 2014-4-12 13:44:51
hochikong 发表于 2014-4-7 11:18
有空研究一下用 python实现一下

哈哈,随便用的头像
回复

使用道具 举报

junzi234 发表于 2014-6-12 09:21:59
额 记得之前也遇到过这个不过越到的是说10亿条
回复

使用道具 举报

lycan 发表于 2014-6-13 11:43:13
学习学习,那不错的
回复

使用道具 举报

june_fu 发表于 2014-8-28 00:26:01
回复

使用道具 举报

12下一页
您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条