19 Feb 12 百度2012校招笔试题分析
暑假的时候老大突然说让我出一套笔试题,我本来还以为是给组内用的,所以我也没花太多时间,凭印象简单拼凑了几个题,圆内随机点和日志那个应该算是比较经典的题目了,其他的都是我现想的。
没想到后来居然成了百度校招的笔试题,早知道我就出的有新意一点了,也不枉费那么多去笔试的人的时间。不过我感觉百度也不怎么在乎笔试成绩,基本上还是看面试结果。我估计好多面试官都没看过笔试题。
第一题 简答(30分)
1. 请写出C++ STL中vector的相关问题。(20分)
(1)在调用成员函数push_back时,其内部的内存分配是如何进行的。(5分)
(2)调用成员函数clear时,内部是如何具体实现的,如果想将其内存释放,该如何操作。(15分)
答题要点:
1、当vector发现预先分配的内存不够用时,会申请一个大小为当前内存更大的地址,并把数据拷贝到新地址中。
2、在调用clear时,vector并不释放内存,只是在内部做一个“空”的标记。如果想释放内存可以参考如下方法:
vector<int> ver(n,0);//需要释放掉的vector
vector<int>().swap(ver);(这样便可释放ver的内存)
2. 请指出下面C语言中foo函数的问题,此函数想统计字符串中的字母a-z分别出现的个数。(10分)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
|
void foo
(
char a[
100
]
,
int cnt[
256
]
)
{
memset
(
cnt
,
0
,
sizeof
(
cnt
)
)
;
/
/
sizeof
(
cnt
)
在这个时候是指针的大小,
32
位系统中永远等于
4
。此问题给
5
分
while
(
*
a !
=
'\
0
'
)
{
+
+
cnt[
*
a];
/
/
因为有中文,所以这里
*
a可能为负数,会越界。指出问题给
5
分
+
+
a;
}
for
(
char c
=
'a'; c
<
=
'z';
+
+
c
)
{
printf
(
"%c: %d\n"
,
c
,
cnt[c]
)
;
}
}
int
main
(
)
{
char a[
100
]
=
"百度abc"
;
int cnt[
256
] ;
foo
(
a
,
cnt
)
;
return
0
;
}
|
第二题 算法与程序设计(40分)
1. 假设我们有rand(s, t)函数,可以返回[s,t]之间的随机小数。请问如何利用该函数在一个半径为R的圆内随机n个点,并给出相应的时间复杂度分析。(15分)
参考答案:
假设一个边长为2R的正方形把圆包住,那么可以调用rand(s, t)函数两次得到正方形内的随机点(x, y)。留下在圆内的随机点即可,这样可以保证随即概率相等。时间复杂度可以按照圆和正方形的面积比得到:
O(n*(πR^2)/4R^2 )=O(n* π/4)
也可在极坐标下通过线性随机θ得到角度,随机R*sqrt(rand(0,R))得到R。不过概率分析会略微复杂一些,关于此类问题,我准备近期专门写一个blog记录,包括在圆内随机点,在简单多边形内随机点等等。
2. 为了分析用户的行为,系统往往需要存储用户的一些query,但是因为query非常多,所以系统不能够存下每一条。假设我们的系统每天只能够存储m个query,现在需要设计一个算法,对用户时时请求的query进行随机选择m个,请给出一个方案,使得每一个query被抽中的概率尽量相等,也请附加相应的分析。需要注意的是,不到最后一刻你并不知道用户的总请求量是多少。(25分)
参考答案:
假设每天总共有n个query,那么目标是使得每一个query被抽中的概率为m/n。
系统设计如下:
1. 开一个大小为m的数组K,前m个query分别依次放入数组K[0..m-1]中。
2. 假设当前的query为第p个(p>m),随机一个[0-p)的整数i,如果i<m,则K[i]=query[p],否则弃掉该query。
概率分析:
首先分析最后一个,也就是第n个query。其被抽中的概率=其随机数i小于m的概率,也就是m/n。再分析第n-1个query的概率。该query放入数组的概率为m/(n-1)。其没有被最后一个query替换的概率为(n-1)/n。所以第n-1个query被抽中的概率为m/(n-1)*(n-1)/n=m/n。
依次类推,第n-2个query被抽中的概率为m/(n-2)*(n-2)/(n-1)*(n-1)/n=m/n。
即:每一个query被抽中的概率均为m/n。
第三题 系统设计题(30分)
现在有一个“服务器-客户端”的实际系统。正常的客户端每1分钟最多发送一条请求到服务器,服务器需要做一个异常客户端行为的过滤系统。假设服务器在某一个时刻收到了客户端A的一条请求,那么1分钟内的客户端的任何其他请求都需要被过滤。现在知道每一个客户端都有一个IPv6的地址可以作为其ID。客户端个数太多,以至于无法全部放到单台服务器的内存hash表中。现在需要简单设计一套系统,使得支持高效的过滤,可以使用多台机器,但要求使用的机器越少越好。请把关键的设计和思想用图表和代码的方式表现出来。
参考答案:
虽然客户端的ID太多,无法放入到内存中,但是1分钟内请求服务器的ID却不会太多。可以根据这个条件进行设计。
申请队列Q, hash表H。H记录了每一个请求的到达时间。服务器收到请求之后:
While (队首的ID请求到达时间超过1分钟)
出队,并且清空hash表H中的相关记录
If 客户端ID存在于H中then
过滤此请求。
else
将此ID放入Q队尾
记录时间到H中,即H[ID]=now()。
另外还有一些开放的设计方法比如简单分布式设计、文件索引、等等