海量数据小内存!从未出现过的数在哪里

news/2024/12/22 13:09:03/

文章目录

    • 题目
    • 要求
      • 1)内存 1G
      • 2)内存 3 KB
      • 3)内存 有限变量
      • 举例

题目

现在有 40 亿个无符号整数,无符号整数的范围是 0 ~ 232-1(42亿+),哪怕 40 亿个数完全不同,在该范围中也总有没有出现过的数,试问如何找到所有该范围中没出现过的数?

要求

1)内存 1G

直接使用位图

常见的存储数据单位有 int,long等,而位图则是采用作为单位来存储数据,使用一个或者多个位来标记某个元素对应的值

位图是通过位数组来表示对应的元素是否存在的。像在本题中无符号整数一共有 232 个,如果使用位数组来表示每个数有没有出现过(0 表示没出现过,1 表示出现过),那么差不多只要花费 500 MB 的空间就可以表示这 232 个数

在这里插入图片描述

那么之后我们只需要遍历这 40 亿个数,如果出现过就将位数组中对应的位置标记为 1,如果从未出现过,那么对应的位一定还是 0

最后位数组中还是 0 的位对应的数就是我们要找的从未出现过的数们

2)内存 3 KB

内存只有 3 KB,但是只需要找到一个没有出现过的数即可

将这 3 KB的内存都拿来申请 int 类型的数组,该数组中元素的个数为 2 的某次方,那么 3 KB最多可以申请到 2 的 9 次方大小(512)的 int 类型的数组

在这里插入图片描述

既然为 2 的某次方,就意味着 512 一定可以被 2 的32 次方整除,那么我们就把 2 的32 次方平均分成 512 份,每一份应该有 2 的 23 次个数

接下来,我们就可以遍历这 40 亿个数,遍历到数字 X,我们就把该数除以 2 的 23 次方,来看看,这个数属于哪个范围,将数组对应的位置的值加一

如果说一共有 2 的 32 次方个数(每个数都是不同的),那么将上面的数进行以上的操作,最后 512 个 int 的值都会是 2 的 23 次方

由于现在只有 40 亿个数,并且只要求找到一个没有出现过的数即可,那就意味着,数组中一定会有一个 int 的值不足 2 的 23 次方

既然如此,就可以将缺少的数定位到该区间内,再将该区间内的值分成 512 份,进行之前类似的操作,每一份就是 2 的 14 次方个数,周而复始,一定能够定位到没有出现过的数

3)内存 有限变量

只提供有限几个变量,如何找到一个没有出现过的数

原理和上面的方法差不多,只不过没有办法申请更多元素的 int 数组罢了,没有办法将 2 的32 次方的数分成更多份,那我们可以进行二分,就有两个区间 [0,231-1] 和 [231,232-1]

如果只有 40 亿个数,将其遍历,找两个变量分别统计两个区间出现的数的个数,最后找到一个没有满 2 的 31 次方的区间,继续二分,那么最多分 32 次,一定能够找到一个没出现过的数

举例

如果理解有困难,我们可以将数量变小,进行举例

比如一共有 9 个数(5,8,2,0,3,2,9,4,3),这 9 个数都在 [0,9] 这个范围内,那么至少有一个数在范围内但是不在提供的 9 个数中,请找出没有出现过的数

按照位图的解法,就相当于内存足够让我们申请一个有 10 位的数组

在这里插入图片描述

依次遍历这 9 个数,如果出现就将对应的位的位置标记成 1,就像下面这样

在这里插入图片描述

遍历完成后,就会发现没出现过的数是 1、6、7

在这里插入图片描述

再举另外一个例子

比如一共有 9 个数(5,8,14,0,10,2,9,4,3),这 9 个数都在 [0,15] 这个范围内,那么至少有一个数在范围内但是不在提供的 9 个数中,只提供 20 个字节的内存,请找出一个没有出现过的数

按照申请数组的方法就应该是这样的

一共只有 20 个字节,那么申请的 int 类型的数组最多有 4 个元素(必须是 2 的某次方),如果将提供的 9 个数分别除以 4 来确定每个数应该存在哪个范围,从而数组对应的位置值加一,比如 9,除以 4 就是 2,那么数组第 2 个值加一。

在这里插入图片描述

遍历完成后

在这里插入图片描述

题目只要求找到一个没出现过的数即可,发现数组下标为 0 的值为 3,没有满 4,说明 0~3 这个范围内一定有数没有出现过,将下一轮搜查的范围限制到 0~3,继续之前的操作

在这里插入图片描述

最后可以发现 1 从未出现过


http://www.ppmy.cn/news/4959.html

相关文章

29.图像卷积代码实现

1. 互相关运算 接下来,我们在corr2d函数中实现如上过程,该函数接受输入张量X和卷积核张量K,并返回输出张量Y。 import torch from torch import nn from d2l import torch as d2ldef corr2d(X,K): # X是输入,K是核矩阵计算二维互…

随着企业信息化发展之源代码防泄密需求分析

源代码防泄密需求: 随着企业信息化发展的日益增长,软件行业厂商之间的竞争也愈加白热化,加上国内对知识产权的不够重视、山寨模仿产品的横行。保护源代码、保证企业的核心竞争力,成为众多软件研发企业的第一要务。那么企业应该如…

【图像分割】遗传算法优化K聚类图像分割【含Matlab源码 1605期】

⛄一、遗传算法优化K聚类简介 文中提出基于优化遗传算法的模糊聚类图像分割算法, 是在上述对遗传算法进行了优化的基础上形成的。不仅根据个体适应度大小和变化快慢自适应调节变异率和交叉率, 提高计算准确性和效率, 另外, 在遗传算法迭代计算中加入基于曲线二阶导数的约束条件…

DSPE-PEG-DBCO磷脂聚乙二醇二苯基环辛炔简介

名称 磷脂聚乙二醇二苯基环辛炔 DSPE-PEG-DBCO 中文名称 二硬脂酰基磷脂酰乙醇胺-聚乙二醇-二苯基环辛炔 英文名称 DSPE-PEG-DBCO 溶剂 部分常规有机溶剂 存储条件 -20冷冻保存,惰性气体保护 保存时间 1年 PEG常规分子量 2000 3400 5000 DSPE-PEG-DBCO DSPE&a…

C语言浮点型的存储

3.14159 1e10可以写成1.010的10次方 1e5 表示 1.010的5次方 int main() {int n 9;//4bytefloat* pFloat (float*)&n;//float 指针访问4的字节printf("n值为:%d", n);//9printf("*pFloat值为:%f\n", *pFloat);//,是以浮点数的视角去看的*p…

DJ13-1 汇编语言程序设计-2

目录 一、数据定义伪指令 1. 格式 2. 操作数 3. 重复操作数 4. 变量的使用 5. 属性定义伪指令 LABEL 6. 表达式运算符 二、符号定义伪指令 伪指令 指示性语句中的伪操作命令,无论表示形式或其在语句中所处的位置都与 CPU 指令相似,因此也称为伪…

JVM之堆

堆的基本内容: Java堆(Java Heap)是虚拟机所管理的内存中最大的一块,Java堆是被所有线程共享的一块内存区域,在虚拟机启动时创建,此内存区域的唯一目的就是存放对象实例,Java 世界里“几乎”所…

Mycat(6):mycat简单配置

1 找到conf/schema.xml并备份 2 配置虚拟表table[在schema里面] 其中 sharding-by-intfile 为rule.xml中的规则 规则文件为conf文件夹中的partition-hash-int.txt 3 配置数据节点dataNode 现在数据库新建3个数据库,skywalking,skywalking1,s…