一个新浪面试题

nkorange 2011-04-28 10:11:33
有一个大小为2G的文件,存储微博里的粉丝关系。文件有两列,每列都是一个整型数。如某一行的两列分别为:123456 654321。
则代表id为654321的用户是id为123456的用户的粉丝。如果用户123456又是654321的粉丝,则称这两个用户互粉。
要求找出文件里所有的互粉用户。
...全文
1691 19 打赏 收藏 转发到动态 举报
写回复
用AI写文章
19 条回复
切换为时间正序
请发表友善的回复…
发表回复
助力实体老徐 2011-06-05
  • 打赏
  • 举报
回复
这个问题,其实没有那么麻烦吧。。。,就是在一个键值对的列表里,找互为键值的元素。只不过元素过大,无法一次全部导入内存。 只是分批读去就可以了。。。。

比如读取前十个到一个二维数组, 然后从第一个开始循环,判断这十个里有没有互为键值对的。循环完了没有,则用另外一个二维数组读取下一个十个,如果这十个也没有,则继续读取。知道找到,输出结果到结果文件,然后break退出,或者没有找到,到文件尾为止。 开始第一个二维数组的第二个循环,等第一个数组全部循环完毕之后,再往第一个数组里读取下一个十个。。。。
fairywell 2011-05-16
  • 打赏
  • 举报
回复
hash 时间上是个问题,2G 的数对 hash 可以做实验看看时间
xry1983 兄的方法比较靠谱,另外可否引入 inverted index 的思想呢
zmr0469 2011-05-08
  • 打赏
  • 举报
回复
1.数据量不是很大时,直接map
2.数据量过大时,mergesort或者hadoop
Oo纳兰筱DoO 2011-05-06
  • 打赏
  • 举报
回复
hash应该可以吧
fenix124 2011-05-04
  • 打赏
  • 举报
回复
别这么快结。每对都整理成前面数字小,后面数字大。以前面数字取一段范围把存到文件里面,然后每个文件单独处理,找到两个相同的数对则互粉数加1。硬盘读写次数较多,内存占用很少。
一名金人 2011-04-29
  • 打赏
  • 举报
回复
关注一下
星空仰望者 2011-04-29
  • 打赏
  • 举报
回复
[Quote=引用 6 楼 xry1983 的回复:]
4.比较拷贝出的内存。可以对这两块内存再进行一次排序,内存A按粉丝ID排序,内存B按用户ID排序,按步骤3的方法,找出A.粉丝ID==B.用户ID者。相等的就是互粉,不等的则移动A或B

[/Quote]
由于分批拷贝出的数据已经比较少了,所以这次排序不会有太高的时间复杂度了。
星空仰望者 2011-04-29
  • 打赏
  • 举报
回复
1 文件很大,针对该文件使用哈希表不可取

2 拷贝一份文件,先对两个文件进行适当排序(读进内存排序好之后再保存):文件A按照用户ID(第一列)排序,文件B按照粉丝ID(第二列排序)。由于重复的Key很多,这种情况尤其适合“计数排序”,时间复杂度只有O(n),楼主自己检索一下“计数排序”的算法吧,《算法导论》里就有。

3 两份文件进行计数排序后,A文件中的数据是按照用户ID(升序)排列,B文件中的数据按照粉丝ID(升序)排列。每次从A文件中按用户ID读取一块内存(依次读取到内存A,直到读到不同ID为止),从B文件中按粉丝ID读取一块内存(内存B)。比较两个ID,若相等,说明有可能存在互粉,若不等,则移动文件A或B,A<B 则移动A,反之则移动B,直到相等。

4.比较拷贝出的内存。可以对这两块内存再进行一次排序,内存A按粉丝ID排序,内存B按用户ID排序,按步骤3的方法,找出A.粉丝ID==B.用户ID者。相等的就是互粉,不等的则移动A或B

5.依次循环。

6.请楼主赶快给分哈。。
zhusizhi007 2011-04-29
  • 打赏
  • 举报
回复
先拷一份,排下序,再将另一份列倒一下再排序。。。。
nkorange 2011-04-29
  • 打赏
  • 举报
回复
看了大家的解法,觉得还是zyl072的答案最合适。文件大小我不记得是不是2G了,不过肯定是不可能都丢到内存里的。分就给他啦!
turing-complete 2011-04-29
  • 打赏
  • 举报
回复
在下,经过半个小时的深思,提出一愚见:

1、此问题的字符串极具特殊性,可以将其转化为整数。以新浪微博为例账号均为10位,用字符串存10个ASC码,占空间10B。用unsigned int存,则占用4B。

2、账号都有个起始号码,不会从0开始,假设,存在起始号为unsigned int start=1827217000;存在最高号 unsigned int end=1837217000;(事实上,这个2G的文件所含有的不重复账号的个数总是有上限且可证的)

3、建立一个结构体,struct person{unsigned int id;person *friends;//关注人列表}

4、建立一个person的数组,person list[end-start]。此后开始读取文件=》
a、读取一行,前面的账号转型为无符号整数former,后见面(粉丝)转为整形follower。
b、将former 加入列表list[follower]的末尾(如果不存在)。(list[follower]这个元素是个列表)
c、到list[former]中查找follower是否存在,存在则将此对输出到文件,并在内存中删除此follower。
showjim 2011-04-29
  • 打赏
  • 举报
回复
数据不重复的情况下,使相关id有序,全部排序以后出现重复就是互粉了。
数据量的大小区别,就是内排序与外排序的区别
绿色夹克衫 2011-04-29
  • 打赏
  • 举报
回复
新浪总是把简单的搞复杂,以为把数据量弄大了就成了难题了。
vipwan 2011-04-29
  • 打赏
  • 举报
回复
2G的话 直接丢内存.NOSQL很多都这样做的.内存可能需要4G

然后 就是 HASH键值对. 倒置这个键值对. 冒泡一遍 重复的就是 互粉了.

这个应该是以 内存换取效率了.

竞天问 2011-04-28
  • 打赏
  • 举报
回复
存的时候应该会用HASH或类似的结构吧
如果是的话就应该很简单了
如果没有的话首要任务是用更有效的结构来存储数据
zyl072 2011-04-28
  • 打赏
  • 举报
回复
2G的话,数据量并不是很大,考虑是文本文件,并且包含空格、换行符, 实际数据应该是只有几百 MB就能存储。直接全部读进来,用HASH 或者 C++ Map(Set) 来存储, 每次插入 A\B 时,判断 B/A 是否已经存在即可。

倘若文件超过 2G,达到几十G或者更大直至内存无法容纳的话,可以参见我在这个帖子的回帖:
http://topic.csdn.net/u/20110309/11/3c8d0e8f-8d06-4909-bd37-184f63f2a871.html

33,010

社区成员

发帖
与我相关
我的任务
社区描述
数据结构与算法相关内容讨论专区
社区管理员
  • 数据结构与算法社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧