c++后台开发面试常见知识点总结(五)场景设计

  • 搜索引擎的实现,会用到哪些重要的数据结构 
  • 设计实现一个HTTP代理服务器 / web服务器 / FTP服务器/
  • 设计实现cache缓存web服务器的网页访问记录
  • 把一个文件快速下发到100w个服务器
  • 将微信用户分为两组,组内的微信用户互相不为好友;用并查集
  • 朋友之间的点对点关系用图维护,怎么判断两人是否是朋友;求朋友圈的个数
  • XX市有多少钢琴调音师傅?(费米问题)
  • 范围1到1000的数,原本有1000个,互不重复,现多出来1个重复的数,怎么找到它
  • 1-100顺序排列,丢失了一个怎么找到(二分法)
  • 先手必胜策略问题
  • 摆象棋的先手必胜策略
  • 一个矩阵,从左上角到右下角,上下左右走,到达右下角的最短路径,
  • 四辆小车,每辆车加满油可以走1公里,车子之间可以互相加油…
  • 秒杀系统的架构设计
  • 两个50亿url文件,找到相同url,内存4g
  • 判断一个图是否连通?(开始说DFS,面试官说不满意,后来说并查集)
  • 洗牌发牌算法
  • 给你1MB的内存,你们怎么设计, 才能使其利用率最高,产生的碎片最少
  • BitMap局限与解决
  • memcache,redis
  • 判断一个QQ号是否存在于40亿个QQ号中,4GB的空间,O(1)的时间
  • 老鼠试毒药问题;
  • 蚂蚁爬杆;
  • 从50亿的整数集合里找出中位数
  • 高德地图是怎么知道高速路哪里堵车了
  • 微信的朋友圈数据在后台应该怎么存放
  • 如果采用LRU的方法,QQ用户的数据在后台存放管理
  • 给定两个线段的端点坐标,如何判断它们是否相交。(用向量叉乘)
  • 王者荣耀是基于TCP还是UDP,为什么?
  • 一个5L的桶子和6L的桶子,打出3L水
  • 要是设计一个高并发服务器,可以从哪些角度去优化
  • 要完成一个微博评论的部分,在用户进入新闻时优先看到自己好友对此新闻的评论,
  • 一亿QQ用户,每个用户都有500好友,每个人都可能玩很多腾讯出的游戏,如何存储能使获取一个人的好友玩的游戏列表。
  • 1000w(L)个整数排序,范围0到100w(S),8g内存,计数排序
  • 给每个组分配不同的IP段,怎么设计一种结构使的快速得知IP是哪个组的
  • 设计一个类似搜索扣扣好友列表,例如输入a显示前缀为a的所有好友
  • 十亿个ip地址排序.
  • 用数据结构模拟浏览器前进后退的操作
  • 64匹马、8赛道,至少多少轮比赛找出速度最快的4匹马?
  • 如何把访问次数过多的IP拉入黑名单
  • 百度搜索的智能提示怎么实现,输入两个字,出来一些热搜
  • 一亿个数字,找出最大的前 20 个
  • 把上亿个字符串进行排序
  • 1G内存,4G url,求重复的url ;或者是对url去重

 

  • 摆象棋的先手必胜策略
  • 微信的附近的人这个功能,如果让你实现,你准备怎么做,
  • 如何设计一个好的字符串hash函数

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

搜索引擎的实现,会用到哪些重要的数据结构   

https://www.cnblogs.com/Leo_wl/p/5470570.html

搜索引擎的索引其实就是实现单词-文档矩阵的具体数据结构。单词-文档矩阵从纵向看,可以得知每列代表某文档包含了哪些单词;从横向看,每行代表了哪些文档包含了某个单词。倒排索引是单词到文档映射关系的最佳实现方式。

单词词典:文档集合中出现过的所有单词构成的字符串集合,单词词典内每条索引项记载单词本身的一些信息(唯一单词ID等)及指向倒排列表的指针。单词词典用来维护文档集合中出现过的所有单词的相关信息,同时用来记载某个单词对应的倒排列表在倒排文件中的位置信息。在查询时到单词词典里查询,就能获得相应的倒排列表,并以此作为后序排序的基础。常用数据结构:哈希加链表和树形词典结构。

哈希加链表词典结构的主体是哈希表,每个哈希表项保存一个指针,指针指向冲突链表,相同哈希值的单词形成链表结构。构建过程:对文档进行分词;对于做好的分词,利用哈希函数获取哈希值;根据哈希值对应的哈希表项找到对应的冲突链表;如果冲突链表已经存在该单词不处理否则加入冲突连表。

树形词典结构:使用B树或者B+树的结构。与哈希表不同的是,需要字典项能按照大小排序,即 使用数字或字符序。树形结构中,使用层级查找,中间节点保存一定顺序范围的词典项,最底层的叶子节点存储单词的地址信息。

倒排列表:倒排列表用来记录哪些文档包含了某个单词。倒排列表由倒排索引项组成,每个倒排索引项由文档ID,单词在文档中出现次数TD,单词在文档中哪些位置出现过等信息。包含某单词的一系列倒排索引项形成了某个单词对应的倒排列表。

建立索引:可以使用两遍遍历文档的方法在内存里完成索引的创建。要求内存要足够大。第一遍遍历收集一些全局的统计信息。包括文档集合包含的文档个数N,文档集合内所包含的不同单词个数M,每个单词在多少个文档中出现过的信息DF。
将所有单词对应的DF值全部相加,就可以知道建立最终索引所需的内存大小是多少。获取信息后,根据统计信息分配内存等资源,同事建立好单词相对应倒排列表在内存中的位置信息。第二遍遍历逐个单词建立倒排列表信息。获得包含某个单词的每个文档的文档ID,以及这个单词在文档中的出现次数TF,然后不断填充第一遍扫描时所分配的内存。当第二遍扫描结束的时候,分配的内存正好被填充满,每个单词用指针所指向的内存区域“片段”,其起始位置和终止位置之间的数据就是这个单词对应的倒排列表。

 

设计实现一个HTTP代理服务器

基本原理:代理服务器作为真实服务器的一个代理端,客户端的请求信息不是直接发送到其真实请求的服务器而是发送到代理服务器,此时代理服务器是作为一个服务器,之后代理服务器通过解析客户端的请求信息,再向真实服务器发送请求报文,获得请求的信息,此时代理服务器是作为一个客户端。 

使用代理服务器的好处是:1. 在请求客户端和真实服务器之间添加了一层,这样就可控的对于请求的响应报文做一些限制或者是改变,例如网站过滤、钓鱼网站等,使得响应到客户端的信息是代理服务器处理过的;2、还有就是请求报文先发送到代理服务器,这样代理服务器可以设立缓存,通过对请求报文解析后代理服务器可以通过查找本地缓存,如果有缓存好的,并且通过向服务器发送是否更新的信息后得到没有修改后就可以直接从代理服务器将响应报文返回给客户端,这样减少了服务端的负载,减少了流量。

https://blog.csdn.net/rocketeerLi/article/details/83717613

 

实现一个web服务器

以FTP服务器为例
首先创建一个服务器socket,然后bind地址,listen监听,然后把socket加入多路转接监听链表。当有连接到达的时候,我们对socket调用accept,返回一个已连接套接字描述符,然后根据用户传输过来的文件名去查找文件,读取文件内容并回送给用户。

accept之后创建一个线程,如果使用线程池的话就从池中取一个空闲线程,然后把已连接文件描述符传给这个线程,然后让线程去处理这个用户请求,一个线程处理一个用户请求。

 

设计一个cache缓存web服务器的网页访问记录,该如何实现这个数据结构?

用队列,根据last visited排序,先进先出;队列每一个元素包含键值两部分,值就是访问的记录。再用一个hash表保存键值,这个值呢是指向队列元素的指针。

 

把一个文件快速下发到100w个服务器(不会)
(面试官之后说你可以想想迅雷是怎么做到下载速度那么快的)

树状: 1. 每个服务器既具有文件存储能力也应具有文件分发能力。

       2. 每个服务器接收到文件之后向较近的服务器分发,具体类似多叉树,应该挺快的。

索引状:1. 设置1000个缓存服务器,文件先下发到这些缓存上。(具体多少缓存、分几层缓存和具体业务有关。) 2. 每个缓存服务器接收1000个服务器取文件。

 

将微信用户分为两组,组内的微信用户互相不为好友;用并查集

我当即说出来逐次探测,又被逼问时间复杂度,O(n2

dfs:微信用户之间的关系图包含很多连通分量的无向图,保存原始关系图G0(邻接矩阵)。拷贝一份可以修改的关系图G1,遍历图G1中每个节点并标记,若节点没有边,则不处理;若节点只有一条边,则将该节点的唯一邻接节点在G0中查找它的所有邻接节点,若hashmap中已有该节点或者有该节点的邻接节点,返回false;否则在图中将该节点的所有边断开,将该节点加入hashmap中;若节点只有多条边,则对该节点自身做上述处理;程序到最后则返回true;还可以用并查集

 并查集:

Pre[100],initial(int n),find(int x),unite(int x,int y)

https://blog.csdn.net/hlk09/article/details/81462771

 

朋友之间的点对点关系用图维护,怎么判断两人是否是朋友;求朋友圈的个数

Dfs 并查集,

http://www.cnblogs.com/grandyang/p/6686983.html

 

XX市有多少钢琴调音师傅?(费米问题)

首先从XX市有多少台钢琴开始,其次弄清楚需要多少调音师才能让这些钢琴保持音准。先列出一些知道的数据,然后是一些假设:

一、钢琴需要多久进行一次调音

二、为一台钢琴进行调音需要多长时间

三、一位钢琴调音师一年平均工作多少小时

四、纽约有多少架钢琴

 

范围1到1000的数,原本有1000个,互不重复,现多出来1个重复的数,怎么找到它

解答:求和相减,把给定的 1001个数相加的和减去(1+2+…+1000)即可得到答案。

 

1-100顺序排列,丢失了一个怎么找到(二分法)

二分法,比如第一次的话,你取arr[50],看看是不是50,如果是,说明缺失的数在后面,如果是49,则缺失的数在[0-49]位置,包括49,依次类推即可

 

先手必胜策略问题:n本书,每次能够拿X-X本,怎么拿必胜,拿到最后剩下的算胜利。

N个糖果,每次只能取1个到6个,不能不取,你先取,请问是否有必胜策略,怎么取。

每次取到只剩7的倍数个糖果即可。因为剩下的为7的倍数时可以保证对方不能一次性取完。当取到最后剩下7个时,对方不能取完,然后自己可以取完。

 

  • 摆象棋的先手必胜策略,每个人每轮摆一个,直到某一个人不能在空白的地方继续放下,就算输,那么你有必胜的方法吗,

第一个人摆在正中心(同心圆),然后不管第二个人怎么摆,第一个人都和他玩中心对称。

 

一个矩阵,从左上角到右下角,每个位置有一个权值。可以上下左右走,到达右下角的最短路径怎么走。

如果只可以向右和向下走可以考虑dp

本题中,可以dfs递归实现。面试官说要优化。说了一下用迪杰斯特拉的思路,说可以。

迪杰斯特拉:https://blog.csdn.net/chen134225/article/details/79886928

 

 四辆小车,每辆车加满油可以走1公里,车子之间可以互相加油,问怎么能让一辆小车走最远。说了好几种方案,面试官引导我优化了一下,但是还是不满意,最后他说跳过。

答:四辆车跑1/4*1公里的时候,把其中一辆车的油分给其他三辆车,此时其他三辆车都满油,抛弃分油车;三辆车继续跑1/3*1公里的时候,把其中一辆车的油分给其他两辆车,此时其他两辆车都满油,抛弃分油车;两辆车继续跑1/2*1公里的时候,把其中一辆车的油分给另一辆车,此时最后1车满油,抛弃分油车,最后一辆车继续跑1公里;

最远跑(1/4+1/3+1/2+1)*公里。

 

秒杀系统的架构设计

https://blog.51cto.com/13527416/2085258?cid=700792

 

两个大文件存url,找相同url ,两个50亿url文件,找到相同url,内存4g

  1. 分别扫描A,B两个文件,根据hash(url)%k(k为正整数,比如k = 1000,k的取值保证内存可以放得下即可)将url划分到不同的k个文件中,比如a0,a1,....a999;b0,b1,...b999;这样处理后相同的url肯定在对应的小文件中(a0 vs b0,a1 vs b1,...a999 vs b999)因为相同的url%1000的值肯定相同,不对应的小文件不可能有相同的url;然后我们只要求出1000对小文件中相同的url即可。比如对于a0 vs b0,我们可以遍历a0,将其中的url存放到hash_map中,然后遍历b0,如果b0中的某个url在hash_map中,则说明此url在a和b中同时存在,保存下来即可。
  2. 布隆过滤器

 

如何判断一个图是否连通?(开始说DFS,面试官说不满意,后来说并查集)

图的遍历方法有dfs,bfs先遍历一遍图,判断是否所有的节点都遍历到

并查集的方法合并节点,最后数一共有多少集合,如果集合是1,证明连通。

 

 

洗牌发牌算法。 说了两种办法

答:1. 每次从未处理的数据中随机取出一个数字,然后把该数字放在数组的尾部,即数组尾部存放的是已经处理过的数字。这是一个原地打乱顺序的算法,算法时间复杂度O(n)。python的shuffle实现方式。

  • 给你1MB的内存,你们怎么设计, 才能使其利用率最高,产生的碎片最少

采用分页法,1MB的内存,每4KB为单位进行,设置一个映射表,非连续性分配。
最坏的情况,只有一个4KB产生碎片。

 

  • BitMap局限与解决
  • 数据碰撞。比如将字符串映射到 BitMap 的时候会有碰撞的问题,那就可以考虑用 Bloom Filter 来解决,Bloom Filter 使用多个 Hash 函数来减少冲突的概率。
  • 数据稀疏。又比如要存入(10,8887983,93452134)这三个数据,我们需要建立一个 99999999 长度的 BitMap ,但是实际上只存了3个数据,这时候就有很大的空间浪费,碰到这种问题的话,可以通过引入 Roaring BitMap 来解决。

 

  • memcache中的数据结构是如何实现的
    • memcache是分布式缓存服务器,通过在内存中缓存数据和对象来减少读取数据库的次数,从而提高动态、数据库驱动网站的速度。memcache中保存的数据都存储在memcache内置的内存存储空间中。重启memcache、操作系统都会导致全部数据消失。当memcache内容容量达到指定值之后,memcache就基于LRU算法淘汰缓存。memcache本身是为缓存而设计的服务器,因此没有过多考虑数据永久性的问题。
  • memcache,redis内部存储数据原理
    • https://blog.csdn.net/session_time/article/details/52618215
    • redis与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

 

  • 判断一个QQ号是否存在于40亿个QQ号中,4GB的空间,O(1)的时间

用bitmap(位图);

根据待排序集合(QQ号)中最大的数,开辟一个位数组,用来表示待排序集合中的整数;待排序集合中的所有数字在位数组中的对应位置置1,其他的置0;

排序过程:将所有的位都置为0;通过读入文件中的每个QQ号检验每一位,如果该位为1,输出对应的整数。,将每个对应的位都置为1;

位图排序时,我们需要考虑:给出一个数,如何找到其对应位图的位置,方法就是首先找到该数对应的字节,然后在找到该数对应的位。例如一个QQ号是:983262245,则将bit的98326625位进行标记。bitset是C++提供的一种位集合的数据结构,它让我们可以像使用数组一样使用位,可以访问指定下标的bit位。因此将通过bitset容器进行存储42亿个qq号码。由于一个字节可以存放8个QQ号码,则4000000000/8/1014/1024 = 500.679Mb,内存合适,通过bit位下表来判断QQ号码是否存在。

bitset<40亿> bit;// 40亿的位图  bit.set(63834199);//将QQ号放入位图对应的位置中 bit.test(qq) 测试qq号是否存在。

https://blog.csdn.net/hpugym/article/details/80008946

 

  • 老鼠试毒药问题:1000 个瓶子中有一瓶毒药,一只老鼠吃到毒药一周之内会死,如果要在一周之内检测出有毒药的一瓶,问至少需要几只老鼠?
    1000个瓶子编号1-1000, 每个编号会有一个10位的二进制数字。 10只老鼠,依次喝掉所有二进制第一位是1的瓶子,第二位是1的瓶子。。。第十位是1的瓶子。 一周之后,死掉的老鼠说明毒药瓶子编号在对应二进制位置是1,否则是0。可以组合出毒药的编号。

 

蚂蚁爬杆:n只蚂蚁以每秒1cm的速度在长为Lcm的竿子上爬行。当蚂蚁爬到竿子的端点时就会掉落。由于竿子太细,两只蚂蚁相遇时,他们不能交错通过,只能各自反向爬回去。对于每只蚂蚁,我们知道它距离竿子左端的距离为Xi,但不知道它当前的朝向,请计算所有蚂蚁落下竿子所需的最短时间和最长时间。

最短时间:如果每只蚂蚁一开始就向着距离自己最近的竿子那一端爬,具体来说,在坐标0~L/2之间的蚂蚁朝着左端爬,L/2~L之间的蚂蚁朝着右端爬,那么蚂蚁之间就不会相遇(因为蚂蚁的速度是一样的)。所以在所有蚂蚁都处于自己最短的时间中只需要取出用时最长的那一个时间作为最终整体的最短用时即可。

最长时间:对于最长时间,得考虑相遇,因为只有不断相遇,不断折返,才能增加蚂蚁的爬行时间;但是如果我们可以不考虑蚂蚁的身份,将所有蚂蚁都视作相同无差别的,相当于每只蚂蚁是独立运动的,每次遇到别的蚂蚁后,就是变身一次而已,并不会影响其运动方向与轨迹。这样的话,求整体最长时间,就只需要求每只蚂蚁最长使用的情况下的最大值即可。

 

从50亿的整数集合里找出中位数. 

这里我说出来了两种方法.  分治法 和 位图法

 

高德地图是怎么知道高速路哪里堵车了,并且还能标记出来准确的路段? 提出你的设想.

通过用户终端反馈的数据进行分析的。汽车的导航、手机用的导航等等,都会定时往服务器上传数据,后台通过你通过该段距离所用的时间,来进行判断是否拥堵。

 

问微信的朋友圈数据在后台应该怎么存放,主要要考虑的存放和读取(你朋友读取),不是系统设计,主要问你用的存储结构就行。

朋友圈用hash表和stack保存,每次更新后你朋友的数据那里会有一个queue去保存你这个新的朋友圈的信息。


如果采用LRU的方法,QQ用户的数据在后台存放管理?

我的理解就是理解成怎么实现对内存里的进行LRU。刚开始的想法有些漏洞,后来自己改进加面试官稍微提醒了一下最后结果感觉他还是比较满意的。

用hash表和链表结合,hash的key用时间结点,这样就能保证查询和插入删除操作都不会特别耗时。再次重申不一定是正确答案,你可以找其他大佬商量探讨

 

给定两个线段的端点坐标,如何判断它们是否相交。(用向量叉乘)

http://acm.hdu.edu.cn/discuss/problem/post/reply.php?postid=32179&messageid=1&deep=0

 

你觉得王者荣耀是基于TCP还是UDP,为什么?(其实答案是有安全保障的UDP,楼主答上了是这个)然后问道具体怎么设计的。(答得不太好)。

TCP使用场景:当对网络通信质量有要求时,比如:整个数据要准确无误的传递给对方,这往往对于一些要求可靠的应用,比如HTTP,浏览器,QQ文件传输;

UDP使用场景:对当前网络通讯质量要求不高的时候,要求网络通讯速度尽量的快,实时,这时就使用UDP ,如QQ语音,QQ视频,王者荣耀。

 

一个5L的桶子和6L的桶子,打出3L水

用装满水的5L倒进6L里,此时6L里还能装1L水,将5L再装满,倒进6L里,5L只能倒进1L,所以还剩下4L,同理,倒空6L,将剩余的4L倒入,再将5L装满,倒入6L里,由于6L只能再装入2L的水,所以,此时5L剩余部分为3L

 

要是设计一个高并发服务器,可以从哪些角度去优化。

https://blog.csdn.net/belalds/article/details/81106866

 

场景题:现在要完成一个微博评论的部分,想在用户进入新闻时优先看到自己好友对此新闻的评论,好友可能有多条评论,怎么设计结构。微博新闻评论设计

每一条新闻对应一个map<int,vector<int>>,key是用户id,value中包括了这个用户所有评论在新闻中的位置。每一条新闻对应一个hashmap存放新闻中的评论位置和评论内容,当前用户访问时,对他的每一个好友id在map里面查找,并对应显示。感觉面试官还比较满意,不过忘记说应该有评论和评论id的对应了,可能关系不大。

 

假如有一亿QQ用户,每个用户都有500好友,每个人都可能玩很多腾讯出的游戏,问如何存储能使获取一个人的好友玩的游戏列表。

用key-value存储,bitmap。使用memcached或redis, redis与memcached一样,为了保证效率,数据都是缓存在内存中。区别的是Redis会周期性的把更新的数据写入磁盘或者把修改操作写入追加的记录文件,并且在此基础上实现了master-slave(主从)同步。

 

1000w(L)个整数排序,范围0到100w(S),8g内存

计数排序  时间:O(1000W+100W)  空间:O(100w)

首先需要两个辅助数组,第一个数组A要记录最终排好序的输出数列(输出数组),大小为n;第二个数组B要记录比某个数小的其他数字的个数,大小应当为K;

1、扫描整个集合S,对每一个Si∈S,找到在线性表L中小于等于Si的元素的个数T(Si);

2、扫描整个线性表L,对L中的每一个元素Li,将Li放在输出数组的第T(Li)个位置上,并将T(Li)减1。

 

设计题,给每个组分配不同的IP段,怎么设计一种结构使的快速得知IP是哪个组的(想用Trie树,面试官让我再优化一下。使用hash,取得ip地址的网络号,使得同一组的ip地址hash值相同。


设计一个类似搜索扣扣好友列表,例如输入a显示前缀为a的所有好友,我说对好友列表用字典树Trie排序,然后面试官说如果给搜索字段很长的话性能不好,然后我说了用文件索引,然后查找索引。

Trie,又称前缀树或字典树,用于判断字符串是否存在或者是否具有某种前缀的字符串。

 

十亿个ip地址排序.

之前在网上查了腾讯很喜欢问这种题目,主要是map reduce和bitmap两种思路去答就可以了.(bitset)

 

  • 用数据结构模拟浏览器前进后退的操作

问题:依次访问完一串页面 a-b-c 之后,点击浏览器的后退按钮,就可以查看之前浏览过的页面 b 和 a。当你后退到页面 a,点击前进按钮,就可以重新查看页面 b 和 c。但是,如果你后退到页面 b 后,点击了新的页面 d,那就无法再通过前进、后退功能查看页面 c 了。

解答思路:1. 使用两个栈,X 和 Y,把首次浏览的页面依次压入栈 X,当点击后退按钮时,再依次从栈X中出栈,并将出栈的数据依次放入栈 Y。点击前进按钮时,依次从栈 Y 中取出数据,放入栈 X 中。当栈 X 中没有数据时,那就说明没有页面可以继续后退浏览了。当栈 Y 中没有数据,那就说明没有页面可以点击前进按钮浏览了。

2. 通过页面 b 又跳转到新的页面 d 了,页面 c 就无法再通过前进、后退按钮重复查看了,所以需要清空栈 Y。

 

  • 64匹马、8赛道,至少多少轮比赛找出速度最快的4匹马?(在提示下优化到12次,最优解为10或者11次)

https://www.cnblogs.com/wuyepeng/p/9740963.html

 

  • 如果把访问次数过多的IP拉入黑名单,怎么实现,用什么数据结构,写个伪码

创建两个Map,一个(ipMap)用来存放用户Ip和访问次数,访问时间等主要信息,另一个(limitedIpMap)用来存放被限制的用户IP。Map的key为用户的IP,value为具体内容。当用户访问系统时,通过IPFilter检查limitedIpMap中是否存在当前IP,如果存在说明该IP之前存在过恶意刷新访问,已经被限制,跳转到异常提示页面;如果limitedIpMap

中不存在则检查ipMap中是否存在当前IP,如果ipMap中不存在则说明用户初次访问,用户访问次数+1,初始访问时间为当前时间;如果存在则检查用户访问次数是否在规定的短时间内进行了大量的访问操作;如果是,则将当前IP添加到limitedIpMap中,并跳转到异常提示页面,否则不进行操作,直接放行本次请求。

  • 来一条设计题。百度搜索的智能提示怎么实现,输入两个字,出来一些热搜

Trie字典树+堆(Top K)吧,然后balabala(第三次。。。感觉面试官不是很满意我的答案)

https://www.cnblogs.com/chenyang920/p/5940190.html

用trie字典树存储大量字符串,以用户输入为前缀,前缀固定时,存储相对来说比较热的后缀。那又如何统计热词呢? TOP K算法统计热词。

 

  • 如果给你 一亿个数字,找出最大的前 20 个。(TOP K 问题),如果我只要第二十个怎么优化。(利用建堆  快速排序)

最大的前 20 个:建立小顶堆,先拿20个数建堆,然后依次添加剩余元素,如果大于堆顶的数(20最小的),用这个数替换堆顶,并调整结构使之仍然是一个最小堆,这样,遍历完后,堆中的20个数就是所需的最大的20个。建堆时间复杂度是O(logK),算法的时间复杂度为O(nlogK)(n为1亿,m为20)。

注:如果数据量大的时候,可以先将数据根据哈希算法打散到各个小文件。每个小文件里,进行同样的操作。接着再把所有小文件的前20个取出。效果应该同理吧。

只要第二十个:利用快速排序;

 

  • 如果给你一个文件,文件里有上亿个无序字符串,设计一个算法把上亿个字符串进行排序。接着把这个有序的字符串输入到一个新的文件当中。(内存有限制)

字符串排序,我采用的是哈希切分,打散至小文件。接着多路归并。

(将大文件切割成小文件,每个小文件内归并排序;对所有的小文件进行归并排序——多重归并排序)

Bitmap、Bloom过滤器

 

  • 1G内存,4G url,求重复的url ;或者是对url去重

将文件通过哈希函数散列成多个小的文件,由于哈希函数所有重复的URL只可能在同一个文件中,在每个小文件中利用一个哈希表做次数统计。就能找到重复的URL。这时候要注意的就是给了多少内存,我们要根据文件大小结合内存大小决定要分割多少文件;本题中分割成4个文件

 

  • 50个红球50个蓝球,放到2个袋子里,从两个袋子各取1个球,让2个都是红球的概率最大,怎么放

把一个红球单独放到一个盒子,另外49个红球和50个篮球放在一个盒子,0.75

 

  • 一个函数返回值为 bool 类型。但是返回 true 与 false 的概率不是百分之五十对百分之五十。要求利用这个函数设计一个新函数,使得新函数的返回值的概率为 50%。

函数返回true与false概率不同,但是函数两次返回为tf与ft的概率是一样的。如果返回结果是tt或ff那么继续调用两次。直至出现tf或ft

 

微信的附近的人这个功能,如果让你实现,你准备怎么做,

地理位置网格分块,存块ID,然后四叉搜索。你的经纬度换算成网格ID,同网格的人撸出来,临近网格的人撸出来,搞定。把地理位置分块,怎么把经纬度转化成网格 ID 呢。本质上就是hash

客户端固定时间发送经纬度(x,y)到服务器s,服务器存储每个登陆的用户的经纬度到表t中,表t按照经纬度分表,将地图分成一个个的小格子。当用户点击“附近的人”时,对用户(x,y)进行计算,最多一次查询其中的4个格子(子表),计算两点间距离获取结果(有点像桶排序)。性能上可以将表t替换为内存结构,容灾即可。
从实际的微信提供的功能来看,附近的人并不太多,估计是其对地图划分的格子很小。

MongoDB的LBS功能实现附近的人

 

https://www.nowcoder.com/discuss/165952?type=0&order=0&pos=414&page=1

 

如何设计一个好的字符串hash函数

对于一个Hash函数,评价其优劣的标准应为随机性或离散性,即对任意一组标本,进入Hash表每一个单元(cell)之概率的平均程度,因为这个概率越平均,两个字符串计算出的Hash值相等hash collision的可能越小,数据在表中的分布就越平均,表的空间利用率就越高。

C++ 11 定义了一个新增的哈希结构模板定义于头文件 <functional>:std::hash<T>,模板类,(重载了operator()),实现了散列函数: unordered_map和unordered_multimap 默认使用std::hash; std::hash;实现太简单

同时,C++ STL 里面实现了一个万用的hash function 针对任何类型的

 

 

boost::hash 的实现也是简单取值。

DJBHash是一种非常流行的算法,俗称"Times33"算法。Times33的算法很简单,就是不断的乘33,原型如下:

hash(i) = hash(i-1) * 33 + str[i],Time33在效率和随机性两方面上俱佳

https://blog.csdn.net/g1036583997/article/details/51910598

 

posted @ 2019-12-24 18:37  程序人生♨︎  阅读(750)  评论(0编辑  收藏  举报