算法通关村 —— 继续研究超大规模数据问题

目录

算法通关村 —— 继续研究超大规模数据问题

1. 对20GB文件进行排序

2.超大文本中搜索两个单词的最短距离

3.从10亿数字中寻找最小的100万个数字


算法通关村 —— 继续研究超大规模数据问题

在接触学习了前面关于海量数据算法的知识和题目后,让我们详细来看几道典型的海量数据场景下的查找问题。

1. 对20GB文件进行排序

题目要求: 假设你有一个20GB的文件,每行一个字符串,请说明如何对这个文件进行排序?

分析: 这里给出大小是20GB,其实面试官就在暗示你不要将所有的文件都装入到内存里,因此我们只能将文件划分成一些块每块大小是xMBx就是可用内存的大小,例如1GB一 块,那我们就可以将文件分为20块。我们先对每块进行排序,然后再逐步合并。这时候我们可以使用两两归并也可以使用堆排序策略将其逐步合并成个

2.超大文本中搜索两个单词的最短距离

题目要求: 有个超大文本文件,内部是很多单词组成的,现在给定两个单词,请你找出这两个单词在这个文件中的最小距离,也就是像个几个单词。你有办法在O(n)时间里完成搜索操作吗? 方法的空间复杂度如何

分析: 这个题咋看很简单,遍历一下,找到这两个单词w1和w2的位置然后比较一下就可以了,然而这里的w1可能在很多位置出现,而w2也会在很多位置出现,如下

算法通关村 —— 继续研究超大规模数据问题_第1张图片

最直观的做法是遍历数组 words找到数组中的每个word1遍历数组words 找到每个word2并计算距离。该做法在最坏情况下的时间复杂度是 O(n2)

优化本题我们少不了遍历一次数组,找到所有word1 和word2出现的位置,但是为了方便比较,我们可以将其放到一个数组里,例如:

listA:{1,2,9,15, 25}
listB:(4,10,19}
合并成
list:{1a, 2a,4b,9a,10b,15a, 19b, 25a}

合并后更方便查找,数字表示出现的位置,后面一个元素表示元素是什么然后一边遍历一边比较就可以了。
但是对于超大文本,如果文本太大那这个list可能溢出

其实不用单独构造list,从左到右遍历数组words,当遍历到 word1时,如果已经遍历的单词中存在word2,为了计算最短距离,应该取最后一个已经遍历到的 word2所在的下标计算和当前下标的距离。同理,当遍历到word2时,应该取最后一个已经遍历到的word1所在的下标计算和当前下标的距离

基于上述分析,可以遍历数组一次得到最短距离,将时间复杂度降低到O(n)。用index1和index2分别表示数组words 已经遍历的单词中的最后一个word1的下标最后一个word2的下标,初始时index1 =index2=-1。遍历数组words,当遇到word2时,执行如下操作:
如果遇到word1则将index1更新为当前下标; 如果遇到word2则将index2更新为当前下标
如果index1和index2都非负,则计算两个下标的距离 index1-index2,并用该距离更新最短距离
遍历结束之后即可得到word1和word2的最短距离。

进阶问题:如果寻找过程在这个文件中会重复多次,而每次寻找的单词不同,则可以维护一个哈希表记录每个单词的下标列表

遍历一次文件,按照下标递增顺序得到每个单词在文件中出现的所有下标。在寻找单词时,只要得到两个单词的下标列表,使用双指针遍历两个下标链表,即可得到两个单词的最短距离。

3.从10亿数字中寻找最小的100万个数字


题目要求:设计一个算法,给定一个10亿个数字,找出最小的100万的数字。假定计算机内存足以容纳全部10亿个数字。

本题有三种常用的方法

1)先排序所有元素,然后取出前100万个数,该方法的时间复杂度为O(nlogn)。很明显对于10亿级别的数据,这么做时间和空间代价太高

2)采用选择排序的方式,首先遍历10亿个数字找最小,然后再遍历一次找第二小,然后再一次找第三小,直到找到第100万个。很明显这种方式的时间代价是O(nm)也就是要执行10亿*100万次,效率很低

3)采用大顶堆来解决,“查小用大堆,查大用小堆”
首先,为前100万个数字创建一个大顶堆,最大元素位于堆顶然后,遍历整个序列,只有比堆顶元素小的才允许插入堆中,并删除原堆的最大元素
之后继续遍历剩下的数字,最后剩下的就是最小的100万个。采用这种方式,只需要遍历一次10亿个数字更新堆的代价是O(nlogn)。堆占用的空间是100万 * 4 B,大约为4MB左右的空间。

如果数据量没有这么大,也是可以直接使用这三种方式的如果将10亿数字换成流数据,也可以使用堆来找,而且对于流数据,几乎只能用堆来做

你可能感兴趣的:(数据结构,算法)