哈希应用之位图

news2025/1/21 11:22:33

文章目录

  • 1.位图概念
  • 2.面试题引入
  • 3.代码解决[配注释]
  • 4.位图应用
    • 4.1找到100亿个整数里只出现一次的整数
    • 4.2找两个分别有100亿个整数的文件的交集[只有1G内存]
      • 1.法一[使用于数据量<=42亿]
      • 2.法二[适用于数据量大>42亿]
      • 3.在一个有100亿个int的文件中找到出现次数不超过2次的所有整数[1G内存]
  • 5.优劣分析
    • 优点
    • 缺点

在这里插入图片描述

1.位图概念

位图,用每一位来存放某种状态,适用于海量数据数据无重复的场景。通常是用来判断某个数据是否存在于海量数据.

2.面试题引入

例如: 经典面试题[腾讯]

现在有40亿个不重复的无符号整数,没排过序。如何快速判断一个无符号整数是否在这40亿个数中。

思考:

1.暴力查找 40亿次
2.排序+二分 最优排序O(N*logN) 二分logN [且二分查找要支持下标访问 文件无法下标查找]
3.哈希表/红黑树 使用的前提是数据在它里面 而40亿整数大小为16G 无法使用

怎么办???面试要挂了吗???要与大厂失之交臂了吗???
不!我要进大厂!那就往下学一下位图!!!

一个无符号整数X是否在给定的整形数据中,需要得到的结果是在或者不在,是两种状态,可以使用一个二进制比特位来代表数据是否存在,假定二进制比特位为1,代表存在,为0代表不存在。这样一个字节8个比特位可以存储8个整数 40亿个整数需要多大空间呢?容易得到的是1G=10亿字节=80亿比特位 一个比特位存储一个整数 40亿个整数需要40亿个比特位 即0.5G

3.代码解决[配注释]

在这里插入图片描述
在这里插入图片描述

//一个比特位变标识两种状态 0 1
template<size_t N>
class bitmap
{
public:

	//构造函数
	bitmap() 
	{
		//开空间 初始化成0
		_bits.resize(N / 8 + 1, 0);
	} 

	//插入: 将数x映射的位 置成1
	void insert_setone(size_t x)
	{
		//第i个字节  0 1 2 3 ...
		size_t i = x / 8;
		//第i个字节的第j个位
		size_t j = x % 8;

		//利用或等 第j位-置1 其余位-不变  
		_bits[i] |= (1 << j);  //左移:并不是向左移而是向高位移
	} 

	//删除: 将数x映射的位 置成0
	void erase_setzero(size_t x)
	{
		//第i个字节  0 1 2 3 ...
		size_t i = x / 8;
		//第i个字节的第j个位
		size_t j = x % 8;

		//利用与等 第j位-置0 其余位-不变 
		_bits[i] &= ~(1 << j);
	}

	//判断: 判断数x是否存在 
	bool judge(size_t x)
	{
		//第i个字节  0 1 2 3 ...
		size_t i = x / 8;
		//第i个字节的第j个位
		size_t j = x % 8;

		//假定数x存在 那么第j位应为1
		//_bits[i]访问到的是 数x所在第i个字节的整体数
		return _bits[i] & (1 << j);
	}

private:
	vector<char> _bits;
};

 测试函数 ///

void test_bitmap1()
{
	bitmap<100> bm;
	bm.insert_setone(10);
	bm.insert_setone(11);
	bm.insert_setone(15);

	cout << bm.judge(10) << endl;
	cout << bm.judge(15) << endl;

	bm.erase_setzero(10);

	cout << bm.judge(10) << endl;
	cout << bm.judge(15) << endl;

	bm.erase_setzero(10);
	bm.erase_setzero(15);

	cout << bm.judge(10) << endl;
	cout << bm.judge(15) << endl;
}

void test_bitmap2()
{
	//4294967295
	//bitset<-1> bm;
	bitmap<0xFFFFFFFF> bm;
}

4.位图应用

4.1找到100亿个整数里只出现一次的整数

///  找到100亿个整数里只出现一次的整数 
//两个比特位变标识三种状态 00-不存在 01-存在一个 10-存在多个
template<size_t N>
class double_bitmap
{
public:

	//插入函数 -- 映射位置1
	void insert_setone(size_t x)
	{
		//数x 第一次进来定走这个if
		// 00 -> 01 原无此数 现有一次
		if (_left.judge(x) == false
		 && _right.judge(x) == false)
		{
			//_right映射位 置1
			_right.insert_setone(x);
		}
		//第二次又来了一个相同数x 走这个else if
		// 01 -> 10  原有一次 现有两次 
		else if (_left.judge(x) == false
			  && _right.judge(x) == true)
		{
			//_left映射位 置1
			//_right映射位 置0
			_left.insert_setone(x);
			_right.erase_setzero(x);
		} 
		//10 :存在多个的数 不用处理 10是多个 再插入一个 还是多个 10
	}

	//输出只存在一次的数
	void Print()
	{
		for (size_t i = 0; i < N; ++i)
		{
			if (_right.judge(i))
				cout << i << endl;
		}
	}

public:
	bitmap<N> _left;
	bitmap<N> _right;
};

///  测试函数  

void test_doublebitmap()
{
	int a[] = { 3, 45, 53, 32, 32, 43, 3, 2, 5, 2, 32, 55, 5, 53, 43, 9, 8, 7, 8 };
	double_bitmap<100> double_bm;
	for (auto e : a)
	{
		double_bm.insert_setone(e);
	}

	double_bm.Print();
}

4.2找两个分别有100亿个整数的文件的交集[只有1G内存]

1.法一[使用于数据量<=42亿]

N+N

时间复杂度与数据个数有关

Step1:将文件一的数据以位图一存储
Sterp2:将文件二的数据一一读取 调用judge函数 判断是否存在于文件一的位图中 若存在 则是交集 将位图一对应位 置成0[当前数已被认定是交集 为防止文件二有重复值 下个与当前数相同的数再来judge时 认定为不存在—去重]

2.法二[适用于数据量大>42亿]

2N+42亿

时间复杂度还与N有关[2^32-1]
计算机知识:计算机所能存储的最大整数:int 在32位机器下 int是4个字节 32个bit 2^32-1

Step1:将文件一的数据映射到位图一
Step2:将文件二的数据映射到位图二
Step3:遍历N[因为100亿个数可能存在计算机所能够存储的42亿个整数里的任意一个 所以要遍历42亿个bit
位] 若两个位图对应位均为1 则为交集

3.在一个有100亿个int的文件中找到出现次数不超过2次的所有整数[1G内存]

用两个bit来标识即可
00:出现0次
01:出现1次
10:出现2次
11:出现2次及以上

5.优劣分析

优点

时间复杂度 空间复杂度小

缺点

只能映射整型 浮点数\string不能用位图

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1064006.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

自动驾驶技术的基础知识

自动驾驶技术是现代汽车工业中的一项革命性发展&#xff0c;它正在改变着我们对交通和出行的理解。本文将介绍自动驾驶技术的基础知识&#xff0c;包括其概念、历史发展、分类以及关键技术要素。 1. 自动驾驶概念 自动驾驶是一种先进的交通技术&#xff0c;它允许汽车在没有人…

字符集、编码格式的理解

计算机中只能存储二进制01&#xff0c; 要想存储字符&#xff0c;就要有一个字符与编码的映射关系&#xff0c;这个关系就是字符集。 字符集就是字符与编码的映射关系* 字符集的发展历程&#xff1a; 因为计算机是欧美先发明的&#xff0c;他们的语言就26个字母&#xff0c;所…

MyBatis-plus使用

1 基础介绍 MyBatis-Plus (opens new window)&#xff08;简称 MP&#xff09;是一个 MyBatis (opens new window)的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。 它已经封装好了一些crud方法&#xff0c;我们不需要再写…

速学数据结构 | 手把手教你会单链表的构建方式

&#x1f3ac; 鸽芷咕&#xff1a;个人主页 &#x1f525; 个人专栏: 《初阶数据结构》《C语言进阶篇》 ⛺️生活的理想&#xff0c;就是为了理想的生活! 文章目录 &#x1f4cb; 前言1. 什么是链表1.1 链表的物理结构1.2 链表的种类 2. 链表的实现一. SList.h 单链表的声明3.…

10. 激光雷达到车身坐标系外参的标定方法(lidar2car)

目录 0. 论文及代码1. 标定原理2. 拟合平面3. 标定roll/pitch/height4. 标定yaw4.1 理解从B_spline拟合的轨迹中得到vehicle航向 5. 精度 0. 论文及代码 参考论文&#xff1a;SensorX2car: Sensors-to-car calibration for autonomous driving in road scenarios 参考代码&…

kafka初体验基础认知部署

kafka 基础介绍 Apache Kafka是一个分布式流处理平台&#xff0c;最初由LinkedIn开发并于2011年开源。它主要用于解决大规模数据的实时流式处理和数据管道问题。 Kafka是一个分布式的发布-订阅消息系统&#xff0c;可以快速地处理高吞吐量的数据流&#xff0c;并将数据实时地分…

医院PACS系统源码 PACS系统源码

医用软件中的影像归档与传输系统软件&#xff08;Picture Archiving and Communication System&#xff0c;简称PACS&#xff09;是一种用于存储、管理和传输医学影像数据的系统。其主要功能包括&#xff1a; 影像存储&#xff1a;PACS可以将医学影像数据以数字化的形式存储在服…

YoloV8训练自己的模型 Pycharm Remote Development

参考视频&#xff1a;https://www.youtube.com/watch?vm9fH9OWn8YM YOLO官方网站&#xff1a;GitHub - ultralytics/ultralytics: NEW - YOLOv8 &#x1f680; in PyTorch > ONNX > OpenVINO > CoreML > TFLite 在本地的pycharm上面建立一个项目 使用scp把代码传…

星球作业(第十一期)Android中Binder简述

Binder 什么是binder&#xff1f;简述下它的工作过程和使用场景。 什么是Binder&#xff1f; Binder是Android中的一个类&#xff0c;实现了IBinder接口&#xff1b; 从IPC的角度来说&#xff0c;Binder是Android中的一种通讯方式&#xff1b; 从Android Framework角度来说&a…

一文搞清楚Java中常见的IO模型

什么是IO 首先&#xff0c;我们要清楚什么是IO&#xff0c;根据冯诺依曼结构&#xff0c;计算机结构分为5部分&#xff1a;运算器、控制器、存储器、输入设备和输出设备。 输入设备和输出设备都属于外设&#xff0c;网卡、硬盘这种既可以属于输入设备也可以属于输出设备。 输入…

深度学习-卷积神经网络-ResNET

文章目录 前言1.resnet2.作者3.精度&#xff08;TOP-5&#xff09;4.论文一览5.竞赛排名6.网络退化7.残差8.残差 1.作者 前言 本文来自B站&#xff1a; ResNet深度残差网络 1.resnet 2.作者 3.精度&#xff08;TOP-5&#xff09; 4.论文一览 5.竞赛排名 6.网络退化 ResNet解…

拆解常见的6类爆款标题写作技巧!

究竟是先写好文章再拟标题还是先确定标题再写文章呢&#xff1f;很多写稿小白都会有这样的疑惑。 在“人人皆可新媒体”的时代&#xff0c;公众号推文类型琳琅满目&#xff0c;每个人都可以建立自己的公众号&#xff0c;写出自己想写的文章。 但怎样起标题、起什么样的标题&a…

MyCat安装文档

JDK安装 JDK具体安装步骤如下&#xff1a; 1. 上传安装包 使用FinalShell自带的上传工具将jdk的二进制发布包上传到Linux 由于上述在进行文件上传时&#xff0c;选择的上传目录为根目录 /&#xff0c;上传完毕后&#xff0c;我们执行指令 cd / 切换到根目录下&#xff0c;查…

STM32 10个工程篇:1.IAP远程升级(六)

在IAP远程升级的最后一篇博客里&#xff0c;笔者想概括性地梳理总结IAP程序设计中值得注意的问题&#xff0c;诚然市面上或者工作后存在不同版本的IAP下位机和上位机软件&#xff0c;也存在不同定义的报文格式&#xff0c;甚至对于相似的知识点不同教程又有着完全不同的解读&am…

You Know What is C++嵌套类

C嵌套类 一、嵌套类1.嵌套类和访问权限2.作用域3.访问控制 一、嵌套类 在一个类的内部定义另一个类&#xff0c;我们称之为嵌套类&#xff0c;或者嵌套类型。引入嵌套类&#xff0c;因为外围类需要使用嵌套类对象作为底层实现&#xff0c;并且该嵌套类只用于外围类的实现&…

黑马JVM总结(二十七)

&#xff08;1&#xff09;synchronized代码块 synchronized代码块的底层原理&#xff0c;它是给一个对象进行一个加锁操作&#xff0c;它是如何保证如果你出现了synchronized代码块中出现了问题&#xff0c;它需要给这个对象有一个正确的解锁操作呢&#xff0c;加锁解锁是成对…

为什么网络安全明明缺口很大,却看起来招聘很少呢?

2023 年我国网络空间安全人才数量缺口超过了 140 万&#xff0c;就业人数却只有 10 多万&#xff0c;缺口高达了 93%。这里就有人会问了&#xff1a; 1、网络安全行业为什么这么缺人&#xff1f; 2、明明人才那么稀缺&#xff0c;为什么招聘时招安全的人员却没有那么多呢&…

10、【Qlib】【主要组件】高频交易嵌套决策执行框架

10、【Qlib】【主要组件】高频交易嵌套决策执行框架 简介简介 日间交易(例如,投资组合管理)和当日交易(例如,订单执行)是量化投资中的两个热门话题,并且通常会分别进行研究。 为了获得日间和当日交易的联合交易绩效,它们必须相互作用,并共同进行回测。为了支持多级的…

7.Tensors For Beginneers - Convector Components

介绍协向量时&#xff0c;曾说过它们有点像 行向量&#xff0c; 行向量确实以某种方式代表了协向量&#xff0c; 这里说明一下&#xff1a; 协向量是不变的&#xff1b; 协向量组件是可变的。 协向量不依赖坐标系&#xff0c;协向量的组件取决于坐标系。 当我们说协向量具有组…