腾讯后台开发笔试题

转自:https://blog.csdn.net/Watson2016/article/details/68502176

1、有1000亿条记录,每条记录由url,ip,时间组成,设计一个系统能够快速查询以下内容

1.给定url和时间段(精确到分钟)统计url的访问次数

2.给定ip和时间段(精确到分钟)统计ip的访问次数

答:首先,1000亿条记录全部放到内存肯定不够,那就是分成小文件了,然后整合;
公共的时间段,因为精确到分钟,我们把这每一分钟建成一个小文件,每个小文件肯定会有许多重复的ip,url;
现在统计每个小的文件中url的访问量和ip的访问次数,方法就是建立索引;
(建立索引的目的是为了减少查询次数,但是随着索引级数增多也会造成花更多的时间在建立索引上);
建立url的索引,假如是www.nowcoder.com/question,可以分别给www.nowcoder.com和question建立索引,那么来了一条url,先看一级索引是不是匹配,匹配再看二级索引,相同的话就是我们要的url目标;
ip的索引也是一样,ip分成4段建立索引;
所以这里影响效率的就是在索引建立这块,索引建立好那就是查询的事了的,就会变得非常快。
假定给定了某个时间段,找出url的访问量,那么先找到给定的时间段,对应着刚开始分割的小的文件(每一个分钟)中搜索,通过索引找到相同的url之后,开始统计,直到搜索完所有的给定时间段内的所有的小的文件;
求ip的访问次数也是一样,按照给定的时间段,找到对应的小的文件,通过索引找到相同的ip后统计,直到搜索完了给定时间段内的所有的小的文件。

 

 

2、实现一个简化的搜索提示系统。给定一个包含了用户query的日志文件,对于输入的任意一个字符串s,输出以s为前缀的在日志中出现频率最高的前10条query。

由于是分布式系统,假设至少有26台机器,每个机器存储以26个字母开头的query日志文件(如机器1存的是a字母开头的,机器2存的是以b字母开头的……)

每个机器上维护着一张哈希表,对于每条query, 在哈希表表中存放其地址(哈希地址为链式的),并对其进行排序,按频率由高到低进行排序。

当用户进行搜索时,可以很快定位到某台机器,并根据哈希表,返回出现频率最高的前10条query。

 

提示:

1、可以预处理日志

2、假设query不超过10亿条,每个query不超过50字节。

3、考虑在大查询量的情况下如何实现分布式服务

答:

可以预处理日志:把hash表的散列函数设计成queryd的前缀相关,然后用哈希表用来定位,大顶堆用来保证拥有相同前缀的query的顺序,当需要更新的时候(某个query的查询频率增加),通过哈希表迅速定位到大顶堆中query所在的节点,然后upHeap进行调整。

分布式考虑:首先有26台服务器分别存储26个字母开头的query。所以首先要设计一个接收用户请求的服务器,这台服务器可以根据用户请求的首字母将查询请求分发给对应26台服务器中的一个(相当于查询请求的路由功能)。还可以考虑利用缓存将最近最常查询的前几条s的结果保存在缓存中,下次再出现s的话可以直接返回结果,并且更新S定位的大顶堆。

 

3、小米公司内部每个员工都会有一个专属的工作邮箱,邮箱的前缀是员工姓名的拼音全拼,例如张强的邮箱是zhangqiang@xiaomi.com,但同时公司里有很多同名的人,为了避免大家相互之间发错邮件,工程师们想了个规则来解决这个问题,即在这些同命人中,入职最早的邮箱前缀为姓名的拼音全拼,第二个入职的邮箱前缀为姓名的拼音全拼后面加“_a”,第三个入职的为姓名的拼音全拼后面加“_b”,以次类推,请按这个规则,如果公司里同时有3位名叫张强的员工,则他们的邮箱分别是zhangqiang@xiaomi.com,zhangqiang_a@xiaomi.com,zhangqiang_b@xiaomi.com...邮箱前缀是员工在公司里的重要标识之一,问题来了:现在小米要举行一次全员野外拉练活动,要求所有员工必须排成一队出去,并且,有的员工要求他必须排在某人的前面或后面,作为组织者的你,收到这样的需求之后,如何给出一个让每个人都满意的排队方式呢?
Java:

1

2

3

4

5

6

7

8

9

10

11

classRequestItem

{

    publicString member;

    publicboolean  standFront; //true表示要排在这个人的前面,false表示要排在这个人的后面

}

classRequest

{

    publicString owner;    //那个人提出的要求

    List<RequestItem> requestItems;    //他要排在哪些人的前面,哪些人的后面

}

List<String> getValidOrder(List<String>allMembers, List<Request> requests);

allMembers就是所有员工的邮箱前缀,requests是一些人的排队要求。小米公司现有几千名员工,每个人最多有10个排队要求(要排在一个人的前面或者后面算一个排队要求),也有人没有什么要求。现在你的任务是完成上面的getValidOrder函数,如果有合法的排队序列,那么返回其中任何一个。否则返回null。

 

答:

这个应该是一个拓扑排序的思想,综合所有人的要求,a要求排在b前面即a指向b的边存在,最终可以生成一个有向图。并在统计条件时统计每个顶点的入度,然后进行拓扑排序。

思想大致如下:首先查找所有入度为0的顶点,如果没有则不存在合法的排队序列,返回null,存在的话放在一个临时队列中。

然后把list中一个员工放进 List<String>中,并把跟该节点相关的节点入度减一,查找是否有节点入度变成了0,有的话把该节点放入list继续遍历,如果没有则查看临时队列

是否还有节点,有的进行遍历,没有的话,如果还有节点没有遍历则返回null。如果所有节点遍历完成则返回list

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值