算法通过村第十五关-超大规模|黄金笔记|超大规模场景


前言


提示:你生命的前半辈子或许属于别人,活在别人的认为里。那把后半辈子还给自己,去追随你内在的声音。 --荣格

理解了前面的几个题目知乎,这里我们在看看在海量数据场景下的查询问题。

对20GB文件进行排序

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

分析:这里给出的大小是20GB,其实面试官在暗示我们不要将所有文件都装入内存里面,因此我们只有将文件划分成块,每块大小是xMB,x就是可用的内存大小,比如如果是1GB的块,那么我们就可以将文件分成20块。我们先对每块进行排序,然后再逐步合并。这时候我们可以使用两两并归,也可以使用堆排序的策略将其逐步合并成一个,相关的可以看以往章节介绍:

这种排序方式也称为外部排序。

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

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

分析:这个题目咋看起来含简单,遍历一下,找到两个单词的位置w1和w2,然后比较一下就可以了,然而这里的w1可能存在多个位置,w2也一样。看下面的图:

在这里插入图片描述

这个时候如何找到最小的距离呢?

最直观的做法就是遍历数组words,对数组中的每个word1,遍历数组words找到每个word2并计算距离。该做法的最坏的时间复杂度为O(n^2),需要优化。

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

ListA:{1,2,3,5,9,34}
ListB:{4,8,12,56}
合并后
List:{1a,2a,3a,4b,5b,12b,34a,56b}

合并成一个之后更方便查找的数组,数字便是出现的位置,后面的一个元素表示元素是什么,然后一遍遍历,一遍比较就可以了。

但是对于超大文本,如果文本太大那么这个list可能会产生溢出,还需要继续观察,我们或发现其实不用单独构造list,从左到右遍历数组words当遍历到word1时,如果已经遍历的单词中存在word2,为了方便记录最短距离,应该取一个已经遍历到的word2所在的下标,计算和当前下边的距离。同理,当遍历到word2时,应该取最后一个已经遍历到的word1所在的下标,计算和当前下标的距离。

经过以上分析,我们可以遍历一次数组就可以得到最短距离,并且将复杂度降低到O(n)。用index1 和index2分别表示数组word已经遍历到单词的最后一个word1和word2下标。初始状态下index1和index2为-1.遍历数组word,当遇到word2时,执行以下操作:

  • 如果遇到word1,则将index1更新为当前下标;如果遇到word2,则将index2更新为当前下标。
  • 如果index1和index2都非负,则计算两个下标的距离|index1 - index 2|,并用该距离更新最短距离。

遍历结束之后就可以获取word1和word2的最短距离。

进阶问题如果再寻找的过程中这个文件会重复多次,而每次寻找的单词不同,则可以维护一个哈希表记录每个短促的下标列表。遍历一次文件,按照下标递增顺序得到每个单词再文件中出现的所有下标。寻找单词时,只需要得到两个单词的下标列表。使用双指针遍历下标链表,就可以得到两个单词的最短距离

从10亿数字中寻找小于100万个数字

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

分析:本题常见的做法有三种

  • 先对元素排序,然后去取出前100万个数字,该方法的时间复杂度为O(nlogn)。很明显这样做时间和空间的消耗很大
  • 采用选择排序,首先遍历10亿个数找最小,然后再遍历一遍找第二小…直到找到100万个。这种方式的时间复杂度(nm),执行10亿*100万次。实现难度高
  • 采用大顶堆来解决。推荐:算法通过村第十四关-堆|白银笔记|经典问题-CSDN博客 堆排序原理。

首先前提创建100万存储空间大顶堆,最大元素位于堆顶。

然后遍历整个序列,只要比堆顶元素小才可以放入堆中。并删除原堆的最大元素。之后继续遍历剩下的序列。直到最后剩下的之后100万个数字。

采用这一种遍历方式,只需要遍历一次10亿个数字,还可以接受。更新堆的代价是O(nlogn),也是勉强够用的。堆的占用空间是100万*4大约就是4MB的空间。也是不错的选择

如果数量没有这么大,上面的其他方法也不是不可以。

如果将10亿数字换成数据流,也可以采用堆的方式,而且对数据流来说,几乎能采用堆来做的。


总结

提示:超大数据排序;超大数据搜索问题;海量数据集遍历;超大规模数据流;堆的排序原理:


如果有帮助到你,请给题解点个赞和收藏,让更多的人看到 ~ ("▔□▔)/

如有不理解的地方,欢迎你在评论区给我留言,我都会逐一回复 ~

也欢迎你 关注我 ,喜欢交朋友,喜欢一起探讨问题。

在这里插入图片描述

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
vc++全版本组件大全 VC++运行时(Visual C++ Runtime)是VC++开发环境中用于支持C和C++程序运行的基础库集合。这些库包含了执行C/C++程序所必需的基本函数和数据结构,例如内存管理、字符串操作、输入输出处理、异常处理等。VC++运行时库分为静态库和动态库两种形式,以适应不同类型的项目需求。 静态链接库 vs 动态链接库 静态链接库(Static Linking Libraries):在编译时,静态库的代码会被直接嵌入到最终生成的可执行文件中。这意味着每个使用静态库的程序都会包含库代码的一个副本,导致最终程序的体积较大,但不需要外部库文件支持即可独立运行。在VC++中,静态链接库的例子有LIBC.lib(用于单线程程序)和LIBCMT.lib(用于多线程程序)。 动态链接库(Dynamic Link Libraries):与静态链接相反,动态库的代码并不直接加入到应用程序中,而是在程序运行时被加载。这使得多个程序可以共享同一份库代码,节省了系统资源。VC++的动态运行时库主要通过msvcrt.dll(或其变体,如MSVCRTD.dll用于调试版本)实现,与之配套的导入库(Import Library)如CRTDLL.lib用于链接阶段。 运行时库的版本 VC++运行时库随着Visual Studio版本的更新而发展,每个版本都可能引入新的特性和优化,同时保持向后兼容性。例如,有VC++ 2005、2008、2010直至2019等多个版本的运行时库,每个版本都对应着特定的开发环境和Windows操作系统。 重要性 VC++运行时对于确保程序正确运行至重要。当程序在没有安装相应运行时库的计算机上执行时,可能会遇到因缺失DLL文件(如MSVCP*.dll, VCRUNTIME*.dll等)而导致的错误。因此,开发完成后,通常需要分发相应的VC++ Redistributable Packages给最终用户安装,以确保程序能够在目标系统上顺利运行。 安装与部署 安装VC++运行时库通常是通过Microsoft提供的Redistributable Packages完成的,这是一个简单的过程,用户只需运行安装程序即可自动安装所需组件。对于开发者而言,了解和管理不同版本的运行时库对于确保应用程序的广泛兼容性和可靠性是必要的。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

师晓峰

啤酒饮料矿泉水,你的打赏冲一冲

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值