百度的一期笔试题

题目和解答转自百科中的一篇文章,但是具体答案以及给分标准是否权威,不得而知,答案和下面我的分析仅供参考,出现任何后果金子概不负责哦。


第一题 简答(30分)



1. 请写出C++ STL中vector的相关问题。(20分)
(1)在调用成员函数push_back时,其内部的内存分配是如何进行的。(5分)
(2)调用成员函数clear时,内部是如何具体实现的,如果想将其内存释放,该如何操作。(15分)


答题要点:

(1)当vector发现预先分配的内存不够用时,会申请一个大小为当前内存大小两倍的地址,并把数据拷贝到新地址中。

金子分析:当调用push-back函数时,先查看配用内存是否足够,如果不够的话,重新分配一段连续的内存,内存大小为原来分配的容量的2倍,然后将原来已经存储的数据复制到新地址,紧接着将要push的数据添在复制数据的后面,最后将原始的分配的内存全部释放。由于push_back会导致地址空间的改变,所以迭代器指向的内容有改变,这点要注意啦。

(2)在调用clear时,vector并不释放内存,只是在内部做一个“空”的标记。如果想释放内存可以参考如下方法:
vector<int> ver(n,0);//需要释放掉的vector
vector<int>().swap(ver);(这样便可释放ver的内存)
金子分析:我怎么觉得跟STL分析的不太一样呢???有待查证资料

给分标准:
1、答案正确给出5分。
2、说明clear的实现方法给5分,说明如何具体释放内存给10分。


2. 请指出下面C语言中foo函数的问题,此函数想统计字符串中的字母a-z分别出现的个数。(10分)
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;
}
金子分析:本题考点,当数组做函数形参的时候,数组名就相当于指针,即使数组名后面指定了数组的大小,编译器也会忽略的。所以想利用memset对数组cnt进行初始化是错误的,该初始化的工作应该放到函数体外,在调用函数前执行。中文字符的那个问题我倒是看出来了,越界在答题的时候估计我也可能想到,不过这个为负数?谁来帮我解答一下,我有点晕。

第二题 算法与程序设计(40分)
1. 假设我们有rand(s, t)函数,可以返回[s,t]之间的随机小数。请问如何利用该函数在一个半径为R的圆内随机n个点,并给出相应的时间复杂度分析。(15分)


参考答案:
假设一个边长为R的正方形把圆包住,那么可以调用rand(s, t)函数两次得到正方形内的随机点(x, y)。留下在圆内的随机点即可,这样可以保证随即概率相等。时间复杂度可以按照圆和正方形的面积比得到:
O(n*(πR^2)/R^2 )=O(n* π)
给分标准:

说出了错误的随机方法可适当给分,给出正确方法给10分,分析了时间复杂度和概率的再给5分。

金子分析:百度很多笔试的题目都跟随机数有关,碰到随机数时的时间复杂度分析我就有点晕,下面第2题也一样,其实都是从《编程珠玑》的题目中衍生出来的。至于本题,我第一次做的时候想到了利用正方形,可以没有想到直接看点是否在圆内,而是想到按照比例将点向内压缩。。。另外一个想法是生成两个随机数,一个是圆内点与圆心距离(<=R),一个是偏转角度[0,360],但是概率是否相等和复杂度分析,我就有点晕了。



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。


金子分析:这完全就是《编程珠玑》中的一道题啊,从n个数中抽取m个数,保证每个数被抽中的概率相等,我会写一篇博客来总结几种方法的。


给分标准:
说出方法即可给分,错误的方法给0-5分,正确的方法给10分。
如果有相应的概率分析也加分,方法错误分析也错误给5分,方法错误分析正确给10分,方法正确分析也正确给15分。




第三题 系统设计题(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()。
给分标准:
简单分布式设计可以按照设计情况适当给5-15分。
建立文件索引的方式也给5-15分。
考虑冗余机制给5分。
此题可以采用单台机器完成,能发现此特点给10分,给出具体方案再给20分。具体方案可参考代码风格等等方面酌情给分。




以上为参考答案,其他符合逻辑的方案可酌情给分


**********************************  测 验 结 束 **********************************
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值