【高阶数据结构】位图

位图

  • 一.位图相关面试题
  • 二.位图的设计及实现
  • 三.C++库中的位图bitset
  • 四.位图的优缺点
  • 五.位图相关考察题目

一.位图相关面试题

问题:给40亿个不重复的无符号整数,没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中(本题为腾讯/百度等公司出过的一个面试题)

  1. 暴力遍历,时间复杂度O(N),太慢。
  2. 排序+⼆分查找。时间复杂度消耗O(N*logN)+O(logN)。深入分析:该思路是否可行,我们先算算40亿个数据大概需要多少内存。1G = 1024MB = 1024 * 1024KB = 1024 * 1024 * 1024Byte约等于10亿多Byte那么40亿个整数约等于16G,说明40亿个数是无法直接放到内存中的,只能放到硬盘文件中。而⼆分查找只能对内存数组中的有序数据进行查找。
  3. 数据是否在给定的整形数据中,结果是在或者不在,刚好是两种状态,那么可以使用一个二进制比特位来代表数据是否存在的信息,如果⼆进制比特位为1,代表存在,为0代表不存在。那么我们设计一个用位表示数据是否存在的数据结构,这个数据结构就叫位图。

二.位图的设计及实现

位图本质是一个直接定址法的哈希表,每个整型值映射一个bit位,位图提供控制这个bit的相关接口。

在这里插入图片描述

  1. 实现中需要注意的是,C/C++没有对应位的类型,只能看int/char这样整形类型,我们再通过位运算去控制对应的比特位。比如我们数据存到vector< int >中,相当于每个int值映射对应的32个值,比如第一个整形映射 0 ~ 31 对应的位,第二个整形映射 32 ~ 63 对应的位,后面的以此类推,那么来了一个整形值x,i=x/32;j=x%32;计算出x映射的值在vector的第i个整形数据的第j位。
  2. 解决给 40 亿个不重复的无符号整数,查找一个数据的问题,我们要给位图开 2 ^ 32 个位,注意不能开 40 亿个位,因为映射是按大小映射的,我们要按数据大小范围开空间,范围是是0 ~ 2 ^ 32 - 1,所以需要开 2 ^ 32 个位。然后从文件中依次读取每个数到位图中,然后就可以快速判断一个值是否在这 40 亿个数中了。
namespace xzy
{//非类型模版参数:N是需要多少比特位template<size_t N>class bitset{public:bitset(){_bs.resize(N / 32 + 1);}//x映射的位标记为1void set(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] |= (1 << j);}//x映射的位标记为0void reset(size_t x){size_t i = x / 32;size_t j = x % 32;_bs[i] &= ~(1 << j);}//x映射的位是1返回真//x映射的位是0返回假bool test(size_t x){size_t i = x / 32;size_t j = x % 32;return _bs[i] & (1 << j);}private:vector<int> _bs;};
}int main()
{xzy::bitset<100> bs1;bs1.set(50);bs1.set(30);bs1.set(90);for (size_t i = 0; i < 100; i++){if (bs1.test(i)){cout << i << "->" << "在" << endl;}else{cout << i << "->" << "不在" << endl;}}bs1.reset(90);bs1.set(91);cout << endl << endl;for (size_t i = 0; i < 100; i++){if (bs1.test(i)){cout << i << "->" << "在" << endl;}else{cout << i << "->" << "不在" << endl;}}//开2^32个位的位图//bit::bitset<-1> bs2;//bit::bitset<UINT_MAX> bs3;//bit::bitset<0xffffffff> bs4;return 0;
}

三.C++库中的位图bitset

https://legacy.cplusplus.com/reference/bitset/bitset/

可以看到核心接口还是set/reset/和test,当然后面还实现了一些其他接口,如to_string将位图按位转
成01字符串,再包括operator[]等支持像数组一样控制一个位的实现。

在这里插入图片描述

int main()
{std::bitset<10000> bs1;cout << sizeof(bs1) << endl;  //1256低层是静态数组array,开的太大容易栈溢出xzy::bitset<100> bs2;cout << sizeof(bs2) << endl;  // 16低层是动态数组vector//解决方法:开到堆上面std::bitset<-1>* ptr = new std::bitset<-1>();ptr->set(10);ptr->reset(10);ptr->test(10);return 0;
}

四.位图的优缺点

  1. 优点:增删查改快,节省空间。
  2. 缺点:只适用于整形。

五.位图相关考察题目

  1. 题目:给定100亿个整数,我们只有1G内存,设计算法找到只出现一次的整数?设计算法找到出现次数不超过2次的所有整数?
  2. 答案:之前我们是标记在不在,只需要一个位即可,这里要统计出现次数不超过2次的,可以每个值用两个位标记即可,00代表出现0次,01代表出现1次,10代表出现2次,11代表出现2次以上。最后统计出所有01和10标记的值即可。
namespace xzy
{template<size_t N>class twobitset{public://00:出现0次//01:出现1次//10:出现2次//11:出现2次以上void set(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2) //00->01{_bs2.set(x);}else if (!bit1 && bit2) //01->10{_bs1.set(x);_bs2.reset(x);}else if(bit1 && !bit2) //10->11{_bs2.set(x);}//11不变}//返回0:出现0次//返回1:出现1次//返回2:出现2次//返回3:出现2次以上int getcount(size_t x){bool bit1 = _bs1.test(x);bool bit2 = _bs2.test(x);if (!bit1 && !bit2) //00{return 0;}else if (!bit1 && bit2) //01{return 1;}else if (bit1 && !bit2) //10{return 2;}else //11{return 3;}}private:bitset<N> _bs1;bitset<N> _bs2;};
}int main()
{xzy::twobitset<100> tbs;int a[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6,6,6,7,9,8,14,14,10 };for (auto e : a){tbs.set(e);}cout << "只出现一次的整数:";for (size_t i = 0; i < 100; ++i){if (tbs.getcount(i) == 1){cout << i << " ";}}cout << endl;cout << "出现次数不超过2次的所有整数:";for (size_t i = 0; i < 100; ++i){if (tbs.getcount(i) == 1 || tbs.getcount(i) == 2){cout << i << " ";}}return 0;
}
  1. 问题:给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集?
  2. 答案:把数据读出来,分别放到两个位图,依次遍历,同时在两个位图的值就是交集。
int main()
{int a1[] = { 5,7,9,2,5,99,5,5,7,5,3,9,2,55,1,5,6 };int a2[] = { 5,3,5,99,6,99,33,66 };bitset<100> bs1;bitset<100> bs2;for (auto e : a1){bs1.set(e);}for (auto e : a2){bs2.set(e);}for (size_t i = 0; i < 100; i++){if (bs1.test(i) && bs2.test(i)){cout << i << endl;}}return 0;
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

解决Qt打印中文字符出现乱码

在 Windows 平台上&#xff0c;默认的控制台编码可能不是 UTF-8&#xff0c;这可能会导致中文字符的显示问题。 下面是在 Qt 应用程序中设置中文字体&#xff0c;并确保控制台输出为 UTF-8 编码&#xff1a; 1. Qt 应用程序代码 在 Qt 中&#xff0c;我们可以使用 QApplic…

hutool糊涂工具通过注解设置excel宽度

import java.lang.annotation.*;Documented Retention(RetentionPolicy.RUNTIME) Target({ElementType.METHOD, ElementType.FIELD, ElementType.PARAMETER}) public interface ExcelStyle {int width() default 0; }/*** 聊天记录*/ Data public class DialogContentInfo {/**…

【算法学习】——整数划分问题详解(动态规划)

&#x1f9ee;整数划分问题是一个较为常见的算法题&#xff0c;很多问题从整数划分这里出发&#xff0c;进行包装&#xff0c;形成新的题目&#xff0c;所以完全理解整数划分的解决思路对于之后的进一步学习算法是很有帮助的。 「整数划分」通常使用「动态规划」解决&#xff0…

【Elasticsearch7.11】postman批量导入少量数据

JSON 文件内的数据格式&#xff0c;json文件数据条数不要过多&#xff0c;会请求参数过大&#xff0c;最好控制再10000以内。 {"index":{"_id":"baec07466732902d22a24ba01ff09751"}} {"uuid":"baec07466732902d22a24ba01ff0975…

Mysql--架构篇--体系结构(连接层,SQL层,存储引擎层,文件存储层)

MySQL是一种广泛使用的关系型数据库管理系统&#xff08;RDBMS&#xff09;&#xff0c;其体系结构设计旨在提供高效的数据存储、查询处理和事务管理。MySQL的体系结构可以分为多个层次&#xff0c;每个层次负责不同的功能模块。 MySQL的体系结构主要由以下几个部分组成&#…

ue5 蒙太奇,即上半身动画和下半身组合在一起,并使用。学习b站库得科技

本文核心 正常跑步动画端枪动画跑起来也端枪 正常跑步动画 端枪动画的上半身 跑起来也端枪 三步走&#xff1a; 第一步制作动画蒙太奇和插槽 第二步动画蓝图选择使用上半身动画还是全身动画&#xff0c;将上半身端枪和下半身走路结合 第三步使用动画蒙太奇 1.开始把&a…

Linux下部署Redis(本地部署超详细)

非docker 1、下载Redis 历史版本&#xff1a; http://download.redis.io/releases 我的&#xff1a; http://download.redis.io/releases/redis-7.0.5.tar.gz 2.安装教程 1.Redis是基于c语言编写的需要安装依赖&#xff0c;需要安装gcc yum install gcc-c 2.查看gcc版…

java -jar启动项目报错:XXX.jar中没有主清单属性

XXX.jar中没有主清单属性 1、错误复现2、错误原因3、解决方案 java -jar启动项目报错&#xff1a;XXX.jar中没有主清单属性 1、错误复现 今天使用springboot给项目打了jar包&#xff0c;使用命令启动时报错&#xff0c;截图如下&#xff1a; 2、错误原因 项目的pom文件配置如…

贪心算法详细讲解(沉淀中)

文章目录 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09;经典例题1.1.1 找零问题1.1.2最小路径和1.1.3 背包问题 2.贪心算法的特点2.1 证明例1 3.学习贪心的方向心得体会 1. 什么是贪心算法&#xff1f;&#xff08;贪婪鼠目寸光&#xff09; 贪心策略&a…

【Logstash03】企业级日志分析系统ELK之Logstash 过滤 Filter 插件

Logstash 过滤 Filter 插件 数据从源传输到存储库的过程中&#xff0c;Logstash 过滤器能够解析各个事件&#xff0c;识别已命名的字段以构建结构&#xff0c; 并将它们转换成通用格式&#xff0c;以便进行更强大的分析和实现商业价值。 Logstash 能够动态地转换和解析数据&a…

unity打包sdk热更新笔记

基础打包需要知识&#xff1a; 安装包大小不要超过2G&#xff0c;AB包数量过多会影响加载和构建&#xff0c;多次IO&#xff0c;用Gradle打包&#xff0c;要支持64位系统&#xff0c;不同的渠道包&#xff1a;让做sdk的人支持&#xff0c;提供渠道包的打包工具 配置系统环境变量…

论文笔记(六十一)Implicit Behavioral Cloning

Implicit Behavioral Cloning 文章概括摘要1 引言2 背景&#xff1a;隐式模型的训练与推理3 隐式模型与显式模型的有趣属性4 policy学习成果5 理论见解&#xff1a;隐式模型的通用逼近性6 相关工作7 结论 文章概括 引用&#xff1a; inproceedings{florence2022implicit,titl…

【Rust自学】12.3. 重构 Pt.1:改善模块化

12.3.0. 写在正文之前 第12章要做一个实例的项目——一个命令行程序。这个程序是一个grep(Global Regular Expression Print)&#xff0c;是一个全局正则搜索和输出的工具。它的功能是在指定的文件中搜索出指定的文字。 这个项目分为这么几步&#xff1a; 接收命令行参数读取…

Vue2+OpenLayers调用WMTS服务初始化天地图示例(提供Gitee源码)

目录 一、案例截图 二、安装OpenLayers库 三、WMTS服务详解 四、完整代码 五、Gitee源码 一、案例截图 二、安装OpenLayers库 npm install ol 三、WMTS服务详解 WMTS&#xff08;Web Map Tile Service&#xff09;是一种标准的网络地图服务协议&#xff0c;用于提供基于…

【STM32-学习笔记-6-】DMA

文章目录 DMAⅠ、DMA框图Ⅱ、DMA基本结构Ⅲ、不同外设的DMA请求Ⅳ、DMA函数Ⅴ、DMA_InitTypeDef结构体参数①、DMA_PeripheralBaseAddr②、DMA_PeripheralDataSize③、DMA_PeripheralInc④、DMA_MemoryBaseAddr⑤、DMA_MemoryDataSize⑥、DMA_MemoryInc⑦、DMA_DIR⑧、DMA_Buff…

lerna使用指南

lerna版本 以下所有配置命令都是基于v8.1.9&#xff0c;lerna v5 v7版本差别较大&#xff0c;在使用时&#xff0c;注意自身的lerna版本。 lerna开启缓存及缓存配置 nx缓存是v5版本以后才有的&#xff0c;小于该版本的无法使用该功能。 初始化配置 缓存配置文件nx.json&am…

html辅助标签与样式表

一、HTML其它常用标签 1.meta标签 &#xff08;1&#xff09;meta标签是一个特殊的HTML标签&#xff0c;提供有关网页的信息&#xff0c;如作者姓名、公司名称和联系信息等 &#xff08;2&#xff09;许多搜索引擎都使用meta标签 <head> <meta name"keyword…

用 Python 从零开始创建神经网络(十九):真实数据集

真实数据集 引言数据准备数据加载数据预处理数据洗牌批次&#xff08;Batches&#xff09;训练&#xff08;Training&#xff09;到目前为止的全部代码&#xff1a; 引言 在实践中&#xff0c;深度学习通常涉及庞大的数据集&#xff08;通常以TB甚至更多为单位&#xff09;&am…

DolphinScheduler自身容错导致的服务器持续崩溃重大问题的排查与解决

01 问题复现 在DolphinScheduler中有如下一个Shell任务&#xff1a; current_timestamp() { date "%Y-%m-%d %H:%M:%S" }TIMESTAMP$(current_timestamp) echo $TIMESTAMP sleep 60 在DolphinScheduler将工作流执行策略设置为并行&#xff1a; 定时周期调度设置…

【机器学习案列】学生抑郁可视化及预测分析

&#x1f9d1; 博主简介&#xff1a;曾任某智慧城市类企业算法总监&#xff0c;目前在美国市场的物流公司从事高级算法工程师一职&#xff0c;深耕人工智能领域&#xff0c;精通python数据挖掘、可视化、机器学习等&#xff0c;发表过AI相关的专利并多次在AI类比赛中获奖。CSDN…