本文为【场景题合集】初版,后续还会进行优化更新,欢迎大家关注交流~
hello hello~ ,这里是绝命Coding——老白~💖💖 ,欢迎大家点赞🥳🥳关注💥💥收藏🌹🌹🌹
💥个人主页:绝命Coding-优快云博客
💥 所属专栏:后端技术分享
这里将会不定期更新有关后端、前端的内容,希望大家多多点赞关注收藏💖
更多历史精彩文章(篇幅过多,不一一列出):
(简历相关)
求职经验分享(1):一份合格的简历应该如何写?-优快云博客(推荐)
求职经验分享(2):简历如何优化以及如何应对面试【后端篇】-优快云博客
(项目亮点相关)
大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(1):Redis篇】-优快云博客
大厂面试官赞不绝口的后端技术亮点【后端项目亮点合集(2)】-优快云博客
(八股文)
大厂面试官问我:Redis处理点赞,如果瞬时涌入大量用户点赞(千万级),应当如何进行处理?【后端八股文一:Redis点赞八股文合集】_java中redis如何实现点赞-优快云博客大厂面试官问我:布隆过滤器有不能扩容和删除的缺陷,有没有可以替代的数据结构呢?【后端八股文二:布隆过滤器八股文合集】_布隆过滤器不能扩容-优快云博客
………
场景题
10亿的数据,找中位数
(1)先通过外排序进行排序再寻找中位数
先将这10G的数据等分成5份存储到硬盘中,然后依次读入一份到内存里面,进行排序,然后将这5份数据进行归并得到最后的排序结果,然后找出中位数第5G大
(2)堆排序(转换为求前5G大的元素)
我们知道利用堆排序处理海量数据的topK是非常合适不过了,因为它不用将所有的元素都进行排序,只需要比较和根节点的大小关系就可以了,同时也不需要一次性将所有的数据都加载到内存;对于海量数据而言,要求前k小/大的数,我们只需要构建一个k个大小的堆,然后将读入的数依次和根节点比较就行了(当然这里的前提是内存需要存的下k个数)
(3)分组
- 每个数4字节,2G能存5亿个。
- 分组,每个组内按照最大基数,分布桶。
- 然后每组都从0号桶开始,拿出数据,当累加到25亿的时候,所有分组的那个桶里都可能存了中位数。因此把问题转换到从这些桶内找中位数。可以继续这个方法。直到只剩一个数。
10亿的数据,1g内存,如何统计
(1)外部排序:
将数据分批读入内存,对每批数据进行排序。
将排序好的数据块写入磁盘。
最后合并所有已排序的数据块,进行统计分析。
(2)两次扫描法:
第一次扫描数据,统计每个值出现的频率,并将结果写入磁盘。
第二次扫描数据,读取磁盘上的频率统计结果,进行最终统计。
(3)分治法:
将数据划分为多个小块,每个小块使用有限内存进行统计。
然后对各个小块的统计结果进行合并。
(4)MapReduce:
将数据分散到多台机器上进行统计。
每台机器统计自己部分的数据,然后汇总结果。
大数据情况下求去最大的top K个
正常排序不可行的原因:在32位的机器上,每个float类型占4个字节,一亿个就要占400MB的存储空间,对于一些可用内存小于400MB的就不可行,显然没办法一次性读入内存进行排序,即使机器可以,方法也不高效
- 局部淘汰,使用冒泡排序
- 每一轮排序能获得最大的那一个,所以经过K轮就可以获得topK
- 时间复杂度 O(KN),空间复杂度 O(K)
- 使用堆来实现
- 用小顶堆,堆顶是最小值。那么新来一个数据,如果小于堆顶,那么就直接抛弃。否则插入堆中
- 时间复杂度O(NlogK),空间复杂度O(K)
如果是找最大的10个,就用10个堆
- 归并
- 把大数据分成N份,每一份内求topK。然后用快排的思想,找到正好为K的那个元素,那么左边的就是答案了。
4.快速排序
找个基准数,如果这个基准数位置大于N,就继续从左边找,否则从右边找
给一个文件,很大,几个G,我们内存只有256MB,每个文件每行都有一个数字,如何做排序呢?
(1)分块读取:
将文件分成多个小的数据块,每个块的大小不超过 256 MB。
将这些数据块逐个读入内存。
(2)内部排序:
对每个小的数据块进行内部排序,可以使用常见的排序算法,如快速排序、归并排序等。
(3)归并排序:
将排序好的小块数据,逐个读入内存进行归并排序。
归并操作时,可以利用磁盘作为临时存储空间,减少内存占用。
1亿行的数字排序
(1)分治
将1亿行分成1000个文件。每个文件内排序,然后每个文件维护一个指针,每次读一个,比较,选最小的加入,该文件的指针+1。
(2)快速排序
(3)归并排序
大文件中返回频数最高的100个词
此处1G文件远远大于1M内存,分治法,先hash映射把大文件分成很多个小文件,
具体操作如下:读文件中,对于每个词x,取hash(x)%5000,然后按照该值存到5000个小文件(记为f0,f1,…,f4999)中,这样每个文件大概是200k左右(每个相同的词一定被映射到了同一文件中)
(2)对于每个文件fi,都用hash_map做词和出现频率的统计,取出频率大的前100个词(怎么取?topK问题,建立一个100个节点的最小堆),把这100个词和出现频率再单独存入一个文件
(3)根据上述处理,我们又得到了5000个文件,归并文件取出top100
/
另外,对于十万个单词中找出重复次数最高的十个单词的问题,可以使用哈希表来统计每个单词出现的次数,并维护一个大小为10的最小堆,遍历哈希表,对于每个单词的出现次数,如果大于堆顶元素,则将堆顶元素替换为当前单词,并对堆进行调整。最终堆中的元素就是重复次数最高的十个单词。
数据类,两个方法插入数据,复杂度O(lgN),查找,复杂度是O(1)。如何实现
- 最大堆和最小堆,维护两个堆堆大小平衡,差距不超过1。最大堆存较小的一半,最小堆存较大的一半。取中位数的时候,取两个堆的堆顶。
你知道网站短链和长链吧?要你设计一个长短链解析系统,且你要考虑有的短链属于热点链接,访问量很多,你怎么设计?
原理:
302 的 HTTP 响应,在响应中包含了长链接地址。浏览器收到响应后,转而去请求长链接地址。
链系统设计主要得解决如下两个问题:
- 如何根据长链生成唯一短链?
- 如何保存短链与长链的映射关系?
我们有 2 个思路生成一个唯一短链,分别是:
- 使用哈希算法生成唯一值
- 使用分布式唯一 ID 生成作为锻炼 ID
索引优化
如果使用关系型数据库的话,对于短链字段需要创建唯一索引,从而加快查询速度。
增加缓存
并发量小的时候,我们都是直接访问数据库。但当并发量再次升高时,需要加上缓存抗住热点数据的访问。
读写分离
短链服务肯定是读远大于写的,因此对于短链服务,可以做好读写分离。
分库分表
如果是商用的短链服务,那么数据量上亿是很正常的,更不用说常年累月积累下的量了。这时候可以一开始就做好分库分表操作,避免后期再大动干戈。
防止恶意攻击
开放到公网的服务,什么事情都可能发生,其中一个可能的点就是被恶意攻击,不断循环调用。
一开始我们可以做一下简单地限流操作,例如:
-
没有授权的用户,根据 IP 进行判断,1 分钟最多只能请求 10 次。
-
没有授权的用户,所有用户 1 分钟最多只能请求 4000 次,防止更换 IP 进行攻击。
简单地说,就是要不断提高攻击的成本,使得最坏情况下系统依然可以正常提供服务。
一个非常大的文件,多行,每行有多个字符串。怎么找出出现频率最高的字符串,以及出现次数。只用一台机器,内存有限。
(1)分块读取:
将文件划分成多个小的数据块,每个块的大小不超过可用内存。
逐个读取数据块到内存中进行处理。
(2)内存统计:
对于每个数据块,使用哈希表(字典)统计每个字符串出现的频率。
由于内存有限,只保留当前块中出现频率最高的前 K 个字符串及其出现次数。
(3)外部归并:
将每个数据块处理后得到的前 K 个高频字符串,写入临时文件。
对这些临时文件进行外部归并排序,得到全局出现频率最高的字符串及其出现次数。
有千万级数据,如何判断一个整数是否存在
对于千万级的数据