百度空间 | 百度首页 
               
 
查看文章
 
出几个技术测试题 - 兼招聘|答案公布
2007-04-20 11:06

创建时间 2007年4月20日

创建人 caoz

首发地址 http://hi.baidu.com/caoz

转载请携带以上标记,谢谢

题目1

现在有两个日志文件,格式为

211.137.1.1

125.65.2.3

202.36.71.33

....

每条一个ip地址。每个日志文件各有100万左右条。文件中可能少部分ip是重复。

现在想知道文件1与文件2中,相同的ip有多少,请编写脚本实现。

小提示:第一,不要吧这个问题复杂化,这是这里最简单的问题。第二,注意程序效率。

答案,此题其实相当简单

将第一个文件遍历读取,存入数组,无须排序,存入即可。

$arr[$ip]=1;

然后遍历第二个文件,针对第二个文件中的每一个ip

查一下是否存在该数组下标

if (isset($arr[$nip])) $sum++;

然后输出$sum即可

其中无任何地方需要排序处理。

题目2

还是刚才那个日志文件,只有一个,100万条ip记录,少部分有重复

现在有一个ip地址库

格式为

ip地址1 - ip地址2 - 地区

这个库有15万条记录

现在请编写脚本,将这100万条记录的地区分布列出来。

小提示,这个题目的关键词是,效率。100万×15万,如果不用点窍门,是不可承受的系统开销,那么很多人都知道索引是提高效率的重要手段,但是基于区间的查询,是不能直接使用索引的,但是,想一下索引的实现原理和效率提升的原理,这个问题就会迎刃而解。很多时候,我们不仅仅要善于利用一些有效的工具,更要明白,这些工具背后的逻辑。

答案,

实际上是要点只有一条,将15万条地区库建立为有序的数组并格式化保存,这个数组会非常有用,做一次排序保存即可,在n多涉及地区查询的实际应用中都可以统一调用,无须每次重新排序。

之后就是最典型的二分查找法了,关键是编写一个二分查找的函数,可以通过不断的二分处理在15万条记录中快速找到该ip所对应的区间,理论每个ip的查找次数是log2(150000),

遍历100万条记录(这100万条记录无须做任何排序),对每个ip判断是否已进行过地区识别,如果没有,则调用二分查找,返回所属地区属性,然后

$sumarea[$return]++; 最后把sumarea排一下序输出即可。

这里唯一的排序是对15万条地区ip区段信息排序,而且只需要进行一次长期保存即可。考核的关键不是排序,而是二分查找,二分查找是最简单的快速索引算法,网上大量资料可查阅。

题目3

现在有2亿web服务的日志,假设就是apache日志或类似格式的日志,没说错,2亿条,格式大体为如下

ip地址,访问url,来路url,当前时间

假设就这些吧,这里可能涉及的是2万个不同的站点。

现在要求,做出每个站点的流量统计,包括这个站点的独立ip数,pv数,时间段分布,地区分布,来路分布,受访分布,Top进入url。

现在给你的电脑是一台双CPU,2G内存的服务器,请考虑实现方式。

小提示,这里的关键词除了效率,还有资源开销,如果我们不考虑数字,只考虑应用,这个题目并不复杂,只是罗嗦,但是当你考虑到要分析2亿个日志,而且对2万个站点每个站点都要做出统计,那么你程序时就可能会遇到一个天大的问题,按照一般的方式处理,内存肯定远远不够用。但是如果大量使用硬盘空间来替代内存,又存在巨大的i/o开销,如何寻找均衡的方式,这里考查的不是脚本编写,而是系统设计。

答案

这道题看上去很唬人,但是实际上只是一个日志切分的问题,不要把系统考虑太复杂

实际上组建一个二步处理的过程,第一步是遍历2亿的日志,然后将每条日志的站点主域取出来,作为文件名,处理到一定数量时批量储存为独立文件。

过程示例如下,处理函数略

$seed=0;

while ($str=fgets($fd))

{

$seed++;

$arr=checklog($str); //将日志切分,将日志中的各个字段切分

$site=$arr["site"];

$vstr["$site"]=$vstr["$site"].$str;

if ($seed>1000000) //假设以100万条日志为内存处理容量

{

    foreach($vstr as $key=>$value)

    {

    $fd=fopen("$path/$key","a");

    fwrite($fd,$value);

fclose($fd);

}

unset($vstr);

$seed=0;

}

}

这个程序执行后,2亿条日志就被分割为2万个文件,每个文件对应一个站点

然后再做一次针对站点的遍历,每个站点分析日志,就属于纯粹的罗嗦体力活了,过程略

该题目中不涉及任何排序操作及算法。这个模式只需要遍历日志两次,此外需要日至容量一倍的写操作,这些代价并不是不能承受的,至少系统设计上很简单。

题目4

小张是某大学的体育部主任助理,为了方便安排体育课程,他做了一个调查,发了1000份问卷,让所有人填写自己所期望的体育课程,这份调查是允许多选。

基本结果为,足球 500份,篮球350份,乒乓球200份,羽毛球200份,网球120份,棒球50份,....

然后小张做了另一个统计,针对每个项目,查看与它共同选择最多的项目,看看冷门项目中,有没有多个项目合并的可能,结果发现,所有选择冷门项目的人,最多的共同选择项几乎都是足球和篮球。那么,是不是说所有项目都与足球,篮球高度相关呢?是不是所有冷门项目都可以并入足球篮球呢?这里的问题在哪里?

如果你是小张,你是否能有更好的处理方法,如有可能,代码实现。

小提示,这是一个基本的关联模型和聚类模型的应用,关联模型中,考虑关联性的因素都包括哪些,共同选择的数字并非唯一的标尺。

答案:

关联模型中,我们不仅需要考虑支持度(共同推举数),也需要考虑置信度(相对比例),这里其实就是一种思维模式的考量,很多时候,我们设计关联模型时,针对不同应用,需要有不同的考量及评估模式,实际应用会比这个题目复杂。

总结

以上都是工作中遇到的实际问题,并非算法考试,和百度程序之星,google程序大赛的模式是不同的,这次招聘面向的目标是非技术部门的数据分析工作,因此并不十分特别强调高效算法,但是强调有解决实际问题的能力,所谓解决实际问题,核心的要求就是简洁高效,从收获的一些答案看,大部分应届生喜欢把问题复杂化,也许是题目描述的问题,不过希望年轻朋友们一定要记住,工作和做学术答辩不一样,一般学生做毕业论文的时候,喜欢化简为繁,简单的问题复杂化,显示卓越的学识和技能,但是工作要求的是化繁为简,用最短时间解决最多的问题,最短的时间不仅仅是程序执行的时间,也包括设计和编码的时间。


类别:默认分类 | 添加到搜藏 | 浏览() | 评论 (11)
 
最近读者:
 
网友评论:
1
2007-04-20 12:05 | 回复
牛人,做个标志
 
2
2007-04-20 13:49 | 回复
题目很有意思,看来每个公司度要考虑效率和资源。
 
3
2007-05-02 17:49 | 回复
caoz,我觉得你这几个问题非常好,我准备拿去做数学模型竞赛试题了,希望caoz不要见怪。
 
4
2007-05-02 23:13 | 回复
呵呵~拿回去看看~感觉有点思路~希望能做出来~
 
5
2007-05-09 14:54 | 回复
呵呵,由于最近在做论文,代码是没时间写了,先说下我对这几个问题大概的思路: 第一题: 排序.将2个日志文件的内容读取到内存,由于估计日志中只是存在少量相同IP,那么用快速排序应该没问题,考虑到排序算法中,肯定有比较的语句,那么在比较时加上一条规则:当A==B时,如何如何.但是这里还存在一个问题,就是题目要求是找出2个日志中相同的IP,那么也就是还需要知道正在比较的IP地址的来源,简便点的办法就是:使用INT数组存储这200W条记录,前100W条来自日志1,后100W来自日志2,那么在比较时再加入对下标的判断,并且找到符合条件的记录时要么重新写入第3个日志,要么再做一个动态增长线性数据结构用来记录. 第二题: 觉得还是用排序的思路,对日志和IP地址库分别排序,日志排序很容易了,IP地址库排序时使用的KEY是IP地址1,也就是起始IP地址,然后遍历排序后的日志文件,并同时遍历排序后的IP地址库,应该是1次遍历就可以统计出来的.这里没有太深入地考虑实现细节. 第三题: 继续排序吧...呵呵...水平有限,只能说自己能想到的方向了,既然内存不够,那外部排序吧,既然是双CPU,那么用1个CPU排序,一个CPU控制IO.就想了这么多,细节没考虑. 第四题: 看了一遍题目,晕了...有时间继续考虑吧...
 
6
2007-05-14 09:55 | 回复
哈哈  这几个题我全拿下了 可惜我还是喜欢回农村种地,农村是一片广阔天地,毛主席说! 哈哈  开个玩笑
 
7
2007-05-22 20:53 | 回复
第一题 IP格式 X1.X2.X3.X4 X1*1+X2*2+X3*3+X4*4 做标识添加到该IP后 按取得数大小排序 然后拿文件2中IP也做X1*1+X2*2+X3*3+X4*4 得到值在然后在文件1中查询 不知道可以不可以?
 
8
2007-05-26 19:48 | 回复
第一题 IP格式 X1.X2.X3.X4 X1*1+X2*2+X3*3+X4*4 做标识添加到该IP后 按取得数大小排序 然后拿文件2中IP也做X1*1+X2*2+X3*3+X4*4 得到值在然后在文件1中查询 不知道可以不可以? 显然有问题 如果我做,决不会写脚本,让数据库来做是最好的方法
 
9
2007-05-28 16:53 | 回复
$fp_a = @fopen ("1.log", "rb"); $fp_b = @fopen ("2.log", "rb"); $stop = array(0=>0,1=>0);//停止标志 $ip = array();//记录IP地址 if($fp_a == "" || $fp_b==""){ exit("没有可比性了!"); } do { if ($stop[0] == 1 && $stop[1] == 1) { break; } if($log1 = fgets($fp_a,1024)){ if($ip[$log1]==""){ $ip[$log1] = 1; }else{ $ip[$log1]++; } }else{ $stop[0] = 1; } if($log2 = fgets($fp_b,1024)){ if($ip[$log1]==""){ $ip[$log1] = 1; }else{ $ip[$log1]++; } }else{ $stop[1] = 1; } } while(true); arsort($ip); for(reset($ip); $key = key($ip); next($ip)) { echo $ip[$key]."
\n"; if($ip[$key]==1){end($ip);} } fclose ($fp_a); fclose ($fp_b); 今天做一个题明天休息时再来做,看对不对哈,下班了......
 
10
2007-05-29 10:26 | 回复
第三题,取样法。数据量越大,这个方法越有效。
 
11
2007-06-01 13:28 | 回复
把两个文件循环放进数组$array[$ip],最后foreach($array as $value),方格计数器$i,如果$value>1;$++。得出结果
 
发表评论:
姓 名:
网址或邮箱: (选填)
内 容:
验证码: 请点击后输入四位验证码,字母不区分大小写
      

     

©2009 Baidu