极限挑战:40亿个非负整数中找到没有出现的数(bit数组)

简介: 大家好!我是小米,一名热衷于技术分享的29岁程序员。今天探讨的问题是在40亿个非负整数中找到未出现的数字。直接使用哈希表因内存限制而不可行。本文提出了一种解决方案——利用bit数组。通过标记出现过的数字,最终找出未被标记的位置所对应的数字即为答案。对于更严格的内存限制(如10MB),文章还介绍了分块处理的方法,先统计每个区间的数字数量,找到计数不足的区间后再精确处理。这种算法不仅展示了巧妙利用有限资源的能力,也为实际工程问题提供了解决思路。希望各位读者能从中受益,享受编程带来的乐趣!



大家好!我是小米,一个积极活泼、热爱分享技术的29岁程序员。今天,我们一起来探讨一个有趣且实用的算法问题:如何在40亿个非负整数中找到没有出现的数。这个问题不仅考验我们的算法设计能力,还需要我们巧妙地利用有限的内存资源。

问题背景

假设我们有40亿个非负整数,并希望找到其中一个没有出现的数。直接使用哈希表来保存所有出现过的数是不现实的,因为最坏情况下40亿个数都不相同,哈希表需要保存40亿条数据。每个32位整数需要4字节,那么40亿个整数大约需要16GB的空间,这显然超过了普通计算机的内存限制。

解决方案:Bit数组

为了节省内存,我们可以采用bit数组来解决这个问题。一个bit数组的每个位置可以存储一个二进制位(0或1),这样每个整数只需一个bit来表示是否出现过。由于bit数组的长度可以刚好覆盖所有可能的非负整数(0到4294967295),我们可以利用这点来设计我们的算法。

基本思路

  1. 申请bit数组:bit数组的大小为4294967296个bit,约为40亿bit。
  2. 空间换算:40亿bit / 8 = 5亿字节,约为0.5GB内存。
  3. 标记出现的数:遍历40亿个非负整数,遇到整数i,则将bit数组中下标为i的位置置为1。
  4. 查找未出现的数:遍历bit数组,找到第一个值为0的位置,该位置对应的整数就是没有出现的数。

代码实现

这段代码使用了一个byte数组来实现bit数组的功能,每个整数对应bit数组中的一个位。在主函数中,我们定义了一个示例的整数列表,并调用findMissingNumber方法来找到其中缺失的数。

进阶解法:内存限制为10MB

如果内存限制为10MB,我们无法直接申请一个大bit数组。此时,我们需要分块处理数据。假设10MB内存可以处理1千万字节的数据,即8千万bit,那么我们可以将40亿个整数分成若干个区间来逐一处理。

分块处理思路

  • 第一遍统计
  • 将40亿个整数按区间划分,每个区间大小为8千万bit
  • 统计每个区间中数的个数,找到一个计数不足的区间。
  • 第二遍处理
  • 针对找到的计数不足的区间,申请一个8千万bit的bit数组。
  • 遍历40亿个整数,将落在该区间的整数映射到bit数组上。
  • 查找未出现的数
  • 遍历bit数组,找到第一个值为0的位置,该位置对应的整数就是没有出现的数。

代码实现

END

通过这篇文章,我们学会了如何在有限内存条件下处理海量数据,找出未出现的整数。我们首先使用bit数组解决大规模数据的问题,然后进一步优化算法以适应更严格的内存限制。这不仅是算法设计中的一种重要技巧,也是实际工程中常见的挑战。

希望大家能从这篇文章中有所收获,继续热爱编程,享受解决问题的乐趣!我是小米,期待在下一篇技术分享中与大家再次相遇。祝大家编码愉快!

我是小米,一个喜欢分享技术的29岁程序员。如果你喜欢我的文章,欢迎关注我的微信公众号软件求生,获取更多技术干货!

相关文章
|
7月前
求两个整数的较大值
两幅图片展示,无文字描述。第一张图链接源为:[结果](https://so.csdn.net/so/search?q=%E7%BB%93%E6%9E%9C&spm=1001.2101.3001.7020)。
39 1
求两个整数的较大值
|
7月前
1657.确定两个字符串是否接近
1657.确定两个字符串是否接近
54 0
|
7月前
|
算法
算法题 — 整数转二进制,查找其中1的数量
算法题 — 整数转二进制,查找其中1的数量
53 0
|
7月前
[leetcode 数位运算] 2578.最小分割和
[leetcode 数位运算] 2578.最小分割和
|
7月前
|
机器学习/深度学习 存储 算法
数据结构与算法面试题:给定非负整数 m 和 n,计算不大于 m 的数字中,素数的个数。(提示:算法原理为埃氏筛、线性筛)
数据结构与算法面试题:给定非负整数 m 和 n,计算不大于 m 的数字中,素数的个数。(提示:算法原理为埃氏筛、线性筛)
102 0
|
机器人 Java 开发工具
生成指定长度的随机数字,用对方法精准提效数10倍!
生成指定长度的随机数字这一函数功能可能在以下情况下被使用:
|
存储 算法 Java
【算法】阿里面试题-编码实现20亿个整数,找出某个数X是否存在其中
【算法】阿里面试题-编码实现20亿个整数,找出某个数X是否存在其中
【算法】阿里面试题-编码实现20亿个整数,找出某个数X是否存在其中
每日一题---输出100个1~6的随机整数,并求出每个数出现的概率
每日一题---输出100个1~6的随机整数,并求出每个数出现的概率
每日一题---输出100个1~6的随机整数,并求出每个数出现的概率
每日一面 - 求与数字最接近的 2 的 N 次方
每日一面 - 求与数字最接近的 2 的 N 次方
每日一面 - 求与数字最接近的 2 的 N 次方
(JAVA编程练习):一个整数,它加上100后是平方数,再加上168又是一个平方数,该数是?+ 输入三个数,进行小到大排序。
(JAVA编程练习):一个整数,它加上100后是平方数,再加上168又是一个平方数,该数是?+ 输入三个数,进行小到大排序。
(JAVA编程练习):一个整数,它加上100后是平方数,再加上168又是一个平方数,该数是?+ 输入三个数,进行小到大排序。