问一道阿里的面试题

AllenSDD 2009-10-09 09:09:47
有4亿条记录。每个记录中都有一些关键字,这些关键字代表了用户所关心的东西。现在需要将这些关键字处理,需要得到出现频率最高的50个关键字,以及出现这么关键字的记录。不能使用数据库,内存为2G。请写出伪码,并说明时间复杂度以及空间复杂度。
...全文
654 21 打赏 收藏 转发到动态 举报
写回复
用AI写文章
21 条回复
切换为时间正序
请发表友善的回复…
发表回复
yijing21 2009-10-20
  • 打赏
  • 举报
回复
楼上的如何统计各个记录的频率,那是未知的,不然就是排序问题了。
liyaodong18 2009-10-19
  • 打赏
  • 举报
回复
将50个关键字的频率,建堆。只讲这个堆载入内存。然后逐个扫描纪录中的频率,与堆顶频率比较,大于堆顶则入堆,小于则不作处理。最终这个堆就是频率最大的50个记录。
tianya0609 2009-10-18
  • 打赏
  • 举报
回复
mark
emailed 2009-10-18
  • 打赏
  • 举报
回复
存下每条记录最多用5个字节,用hash存储int,这就用了4个字节了,剩下一个字节那些关键字根本存不下,所以hash不行
[Quote=引用 1 楼 litaoye 的回复:]
阿里也问这道题么?2G内存,看来是要转化为整型的Hash了,4亿条记录,应该不容易出现hash冲突!
[/Quote]
emailed 2009-10-18
  • 打赏
  • 举报
回复
一直暗示内存不够。。。。我觉得这个题应该不是考存到磁盘上,只是你提出这个观点,面试官问你怎么做而已。另外我觉得字典树比较靠谱
whywen_MoJian 2009-10-17
  • 打赏
  • 举报
回复
mark
帖子不能编辑 2009-10-15
  • 打赏
  • 举报
回复
这就是个统计单词频率问题。
只不过这次,要统计的单词太多了。
KingWolfOfSky 2009-10-15
  • 打赏
  • 举报
回复
看看~~
LeonTown 2009-10-12
  • 打赏
  • 举报
回复
可能是需要保存到磁盘上,
最后,用败者树从磁盘上作归并。

[Quote=引用 11 楼 allensdd 的回复:]
其实面试官面试的时候,我回答的大概思想也是使用字典或者map之类的办法。面试官一直向我暗示内存不够使,我回答说可以保存一部分在磁盘上,他又问我具体怎么做。高人解答一下
[/Quote]
Torey 2009-10-12
  • 打赏
  • 举报
回复
每个关键字写成一个文件,里面内容是次数
threeleafzerg007 2009-10-10
  • 打赏
  • 举报
回复
我曾经答过:

我觉得 字典树 (键树) 比较靠谱。

a b c ....z


例子:

1. 开始遍历第一条 记录

2. 解析出第一个产品词 (比如以空格 或者 ;为分隔符)

3. 开始检索字典树,检索的同时 也是 生成字典树的过程。检索到时,那个树节点 count ++ (初始为0)

4. 重复 2 直至 最后一个 产品词

5 重复 1 直至最后一个记录


#define ALPHA_SIZE 26
#define DELIMITER ';'

typedef struct _KeyTreeNode {
int ncount;
_KeyTreeNode *subTree[ALPHA_SIZE];
}KeyTreeNode;


void initKeyTreeNode(KeyTreeNode *node)
{
node->ncount = 0;
for(int i = 0; i < ALPHA_SIZE; i++)
{
node->subTree[i] = NULL;
}
}

void traverseRecord(KeyTreeNode *root,FILE *fp)
{
if(NULL == root || NULL == fp)
return ;

char buf[255];
char *p = NULL;

while(!feof(fp))
{
memset(buf,0x00,sizeof(buf));
fgets(buf,255,fp);
while((p = strtok(buf,DELIMITER)) != NULL)
{
traverseWork(root,p);
}
}

}

void traverseWord(KeyTreeNode *node , const char *word)
{
KeyTreeNode *q;
const char *p;
for(p = word,q = node; p != NULL && *p != '\0' ; p++)
{
if( NULL == q->subTree[*p-'a'] )
{
q->subTree[*p-'a'] = (KeyTreeNode*)malloc(sizeof(KeyTreeNode));
initKeyTreeNode(q->subTree[*p-'a']);
}
if(*(p+1) == '\0')
q->subTree[*p-'a']->ncount++;
else
q = q->subTree[*p-'a'];
}

}

int main(int argc , char **argv)
{
KeyTreeNode *keytree = (KeyTreeNode*)malloc(sizeof(KeyTreeNode));
initKeyTreeNode(keytree);

fp = fopen("database.txt","r");

traverseRecord(keytreemap,fp);

return 0;
}

AllenSDD 2009-10-10
  • 打赏
  • 举报
回复
其实面试官面试的时候,我回答的大概思想也是使用字典或者map之类的办法。面试官一直向我暗示内存不够使,我回答说可以保存一部分在磁盘上,他又问我具体怎么做。高人解答一下
showjim 2009-10-10
  • 打赏
  • 举报
回复
条件很模糊,需要准备多套方案
超级大笨狼 2009-10-10
  • 打赏
  • 举报
回复
利用C#写这类程序有很多现成的数据结构可以用,链表,哈希都是现成的,除了二叉树要自己写外,其他的都不要自己考虑细节,复杂度早有定论,我在这里推销一下.net
:)
超级大笨狼 2009-10-10
  • 打赏
  • 举报
回复
寻找最大K个元素,在C#里利用K长的SortedList就可以了。

插入的时候判断是不是比最小的还大,是的话就把最小的移出,把新的插入,至于他里边怎么排序,微软已经做过优化,不必考虑,肯定最终是T(n*log k)拉,否则地球人都被雷到了。
AllenSDD 2009-10-10
  • 打赏
  • 举报
回复
顶啊,高人多多解答
超级大笨狼 2009-10-10
  • 打赏
  • 举报
回复
哈希表,C#
Dictionnary<string,List<int>>

其中string是关键字,List是记录号的链表,插入一次,复杂度O(n)

频率最高的50个关键字,寻找最大K个元素,复杂度T(n*log k) 。

总的复杂度:O(n)+T(n*log k)
wenzheng38 2009-10-10
  • 打赏
  • 举报
回复
“他说有4亿条记录,每条记录有一些关键字”,这样算下来关键字个数很大的
不知2G内存够用不?
如果其重复性比较大,用hash遍历一遍应该就可以了
mengde007 2009-10-09
  • 打赏
  • 举报
回复
可以用树堆来解决;借点不超过200个;一次遍历;
绿色夹克衫 2009-10-09
  • 打赏
  • 举报
回复
阿里也问这道题么?2G内存,看来是要转化为整型的Hash了,4亿条记录,应该不容易出现hash冲突!

33,008

社区成员

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

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