哈希应用位图 | 位图概述与代码实现 | 关于位图的几个面试题

news2025/1/14 18:13:59

文章目录

        • 1.位图的概述与实现
          • 1.1.位图的引出与概述
          • 1.2.位图的代码实现
          • 1.3.位图的应用及其他面试题

1.位图的概述与实现

当然C++库中也有位图的实现:链接

1.1.位图的引出与概述

面试题:给40亿个不重复的无符号整数(0~2^32),没排过序。给一个无符号整数,如何快速判断一个数是否在这40亿个数中

能不能,将40亿个排序 + 二分查找,又或者整数存放在map或set,理论上是可以的只要你的内存足够大!无符号整数在32位机器下要用32个比特位来存放,我们按40个比特位算40亿个需要160亿个字节,那么1G大概是10亿个字节,存放40亿个无符号整数要16G左右的内存空间,普通配置的电脑是存放不下的!

能不能一个整数对应用一个比特位来标定

32位标定一个整数的状态是在不在,太浪费,我们可以使用1个比特位通过哈希的直接定址法来标定整数的状态。1G是80亿个比特位,那么40亿个无符号整数大概就是0.5G的内存。

这里就是所谓的位图 ,就是用每一位来存放某种状态,适用于海量数据场景。通常是用来判断某个数据存不存在的。

1.2.位图的代码实现

位图的实现

在这里插入图片描述

一个位图中可以使用vector<int>来存放,40亿有很多个int,我们可以是使用 n / 32找到整数n存放第几个int位置,再通过n % 32找到存放在哪个比特位上,如果是添加,将对应的比特位通过位运算将其置成1即可,如果是删除将对应的比特位通过位运算将其置成0即可。

添加操作

将对应的比特位置成1即可

void set(int n) 
{
	size_t index = n / 32;
	size_t bit_index = n % 32;
	_bitset[index] |= (1 << bit_index);
}

下面假设要将下标为2的比特位置成1:

在这里插入图片描述

让1左移2位,然后或运算,或等是为了改变状态。这里不用考虑大小端的问题,1左移是向高位移动,至于大端还是小端怎么样是机器内部的事!删除和查找是类似的!

删除操作

void reset(int n) 
{
	size_t index = n / 32;
	size_t bit_index = n % 32;
	_bitset[index] &= (~(1 << bit_index));
}

查找操作

bool test(int n) 
{
	size_t index = n / 32;
	size_t bit_index = n % 32;
	return _bitset[index] & (1 << bit_index);
}

完整代码

#include<vector>
#include<iostream>
namespace xiYan
{
	template<size_t N>
	class bitset
	{
	public:

		bitset() {
			_bitset.resize(N, 0);
		}
		void set(int n) 
		{
			size_t index = n / 32;
			size_t bit_index = n % 32;

			_bitset[index] |= (1 << bit_index);
		}
		bool test(int n) 
		{
			size_t index = n / 32;
			size_t bit_index = n % 32;

			return _bitset[index] & (1 << bit_index);
		}
		void reset(int n) 
		{
			size_t index = n / 32;
			size_t bit_index = n % 32;

			_bitset[index] &= (~(1 << bit_index));
		}
	private:
		std::vector<int> _bitset;
	};
}

// 测试代码
#include"bitset.h"
using namespace std;

void main() {
    // 32位大概是43亿个无符号整数,如果是40亿个,我们直接开辟sizt_t的最大值(-1)即可
    // xiYan::bitset<-1> bs;
	xiYan::bitset<100> bs;

	int arr[] = { 1,7,4,3,22,9,7 };

	for (auto num : arr) {
		bs.set(num);
	}
	cout << bs.test(7) << endl;
	cout << bs.test(17) << endl;;


	bs.reset(7);
	cout << bs.test(7) << endl;
    return 0;   
}
1.3.位图的应用及其他面试题
  1. 给定100亿个整数,设计算法找到只出现一次的整数

需要找到出现一次的整数,说明1个比特位标记在不在的状态是不行了!我们可以考虑用两个比特位来标识00 01 10 11其中01标识只出现一次。

在这里插入图片描述

用一个位图中的两个比特位来标识。

在这里插入图片描述

用两个位图对应的比特位来表示,显然是方式2好,可以直接复用位图的结构!方式1要考虑如何切分出两个比特位还需要重新写一遍代码,麻烦些。

方式2的完整代码

#pragma once
#include<vector>
#include<iostream>
#include<bitset>

namespace xiYan
{
	template<size_t N>
	class towBitset
	{
	public:
		void set(int n)
		{
			if (!_one.test(n) && !_tow.test(n)) {
				_one.set(n);
			}
			else if (_one.test(n) && !_tow.test(n)) {
				_tow.set(n);
				_one.set(n);
			}
			else {
				return;
			}
		}
		bool test(int n) {
			return (_one.test(n) && !_tow.test(n));
		}
	private:
		std::bitset<N> _one;
		std::bitset<N> _tow;
	};
}

// 测试代码
#include"bitset.h"
using namespace std;

void test2()
{
	xiYan::towBitset<100> bs;
	// 这里没考虑负数的情况
	int arr[] = { 1,7,7 };

	for (auto num : arr) {
		bs.set(num);
	}
	cout << bs.test(7) << endl;
	cout << bs.test(2) << endl;
	cout << bs.test(1) << endl;
}
  1. 给两个文件,分别有100亿个整数,我们只有1G内存,如何找到两个文件交集

在这里插入图片描述

100亿个整数有好多重复的数字,求交集不需要重复的,所以只需要将数据存放到两个位图中,然后对两个位图中的两个对应的位置按位与如果是0则不是交集,非0则是交集。

  1. 变形:1个文件有100亿个int,1G内存,设计算法找到出现次数不超过2次的所有整数

和第一个题相似,只不过,00 01 10 11 则10表示出现两次!

位图的应用

  1. 快速查找某个数据是否在一个集合中
  2. 排序 + 去重
  3. 求两个集合的交集、并集等
  4. 操作系统中磁盘块标记
  5. 操作系统中文件使用open系统调用的flage选项传入多个参数的时候也使用到了位图
int open(const char *pathname, int flags)
int fd = open("log1.txt",O_WRONLY | O_CREAT | O_TRUNC);

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

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

相关文章

消息中间件之RocketMQ源码分析(十一)

Namesrv路由原理 Namesrv获取的Topic路由信息来自Broker定时心跳&#xff0c;心跳时Broker将Topic信息和其他信息发送到Namesrv。 Namesrv通过RequestCode.REGISTER_BROKER接口将心跳中的Broker信息和Topic信息存储在Namesrv中 路由注册 registerBrokerWithFilterServer()方…

手撕扩散模型(一)| 训练部分——前向扩散,反向预测代码全解析

文章目录 1 直接使用 核心代码2 工程代码实现2.1 DDPM2.2 训练 三大模型VAE&#xff0c;GAN&#xff0c; DIffusion扩散模型 是生成界的重要模型&#xff0c;但是最近一段时间扩散模型被用到的越来越多的&#xff0c;最近爆火的OpenAI的 Sora文生视频模型其实也是用了这种的方…

【Java期末】学生成绩管理系统(MySQL数据库)

诚接C语言、C、Java、Python、HTML、JavaScript、vue、MySQL相关编程作业&#xff0c; 标价10-20每份&#xff0c;如有需要请加文章最下方QQ。 本文资源&#xff1a;https://download.csdn.net/download/weixin_47040861/88856340 1.题目要求 学生成绩管理系统 通过Java控制…

PNG图片压缩-UPNG.js参数说明及示例

UPNG.js是一个非常轻量且高效的库&#xff0c;用于处理PNG图像。它可以编码和解码PNG图片&#xff0c;同时支持压缩和解压缩功能。特别适合在前端项目中处理图像&#xff0c;尤其是在需要优化图像大小而不牺牲质量时。 UPNG.encode()函数是UPNG.js中用于将图像数据编码成PNG格…

量化巨头“卖空”被刷屏!网友:又一类量化策略要“收摊”了

量化圈遇到了龙年首宗“大事件”&#xff01; 2月20日晚间&#xff0c;沪深交易所同时出手对量化巨头灵均投资的异常交易行为进行“处理”。 沪深交易所均称发现灵均在2月19日开盘1分钟内&#xff0c;名下多个账户通过计算机程序自动生产交易指令&#xff0c;短时间大量下单卖…

WireShark 安装指南:详细安装步骤和使用技巧

Wireshark是一个开源的网络协议分析工具&#xff0c;它能够捕获和分析网络数据包&#xff0c;并以用户友好的方式呈现这些数据包的内容。Wireshark 被广泛应用于网络故障排查、安全审计、教育及软件开发等领域。接下将讲解Wireshark的安装与简单使用。 目录 Wireshark安装步骤…

过了30岁了,一定要专注一件事情?视频号值得尝试!

经常说视频号下载助手&#xff0c; 但发现大多数的大佬都只是先专注一件事情。 小编初6就回来了&#xff0c;和一个大佬吃饭&#xff0c;虽然人家规模并不大&#xff0c;但日引客户上千也是基本的。 这里给大家揭秘一下&#xff0c;他的做法&#xff01;&#xff01;&#x…

猫头虎分享已解决Bug || 脚本执行错误(Script Execution Failure):ScriptError, ExecutionFailure

博主猫头虎的技术世界 &#x1f31f; 欢迎来到猫头虎的博客 — 探索技术的无限可能&#xff01; 专栏链接&#xff1a; &#x1f517; 精选专栏&#xff1a; 《面试题大全》 — 面试准备的宝典&#xff01;《IDEA开发秘籍》 — 提升你的IDEA技能&#xff01;《100天精通鸿蒙》 …

挑战30天学完Python:Day15 错误类型

&#x1f4d8; Day 14 &#x1f389; 本系列为Python基础学习&#xff0c;原稿来源于 30-Days-Of-Python 英文项目&#xff0c;大奇主要是对其本地化翻译、逐条验证和补充&#xff0c;想通过30天完成正儿八经的系统化实践。此系列适合零基础同学&#xff0c;或仅了解Python一点…

Linux编辑器——Vim详解

目录 ⭐前言 ⭐vim的基本概念 ⭐vim的基本操作 ⭐vim命令模式命令集 ⭐vim末行模式命令集 ⭐简单vim配置 ⭐配置文件的位置 ⭐常用配置选项 ⭐前言 vi/vim的区别简单点来说&#xff0c;它们都是多模式编辑器&#xff0c;不同的是vim是vi的升级版本&#xff0c;它不仅兼容…

课程大纲:图像处理中的矩阵计算

课程名称&#xff1a;《图像处理中的矩阵计算》 课程简介&#xff1a; 图像处理中的矩阵计算是图像分析与处理的核心部分。本课程旨在教授学员如何应用线性代数中的矩阵计算&#xff0c;以实现各种图像处理技术。我们将通过强调实际应用和实践活动来确保学员能够理解和掌握这些…

代码随想录算法训练营第三六天 | 无重叠区间、划分字母区间、合并区间

目录 无重叠区间划分字母区间合并区间 LeetCode 435. 无重叠区间 LeetCode 763.划分字母区间 LeetCode 56. 合并区间 无重叠区间 给定一个区间的集合 intervals &#xff0c;其中 intervals[i] [starti, endi] 。返回 需要移除区间的最小数量&#xff0c;使剩余区间互不重叠…

vue3 之 商城项目—会员中心

整体功能梳理 1️⃣个人中心—个人信息和猜你喜欢数据渲染 2️⃣我的订单—各种状态下的订单列表展示 路由配置&#xff08;三级路由配置&#xff09; 准备模版member/index.vue <script setup> </script><template><div class"container">…

深度学习图像算法工程师--面试准备(1)

1 请问人工神经网络中为什么 ReLU 要好过于 tanh 和 Sigmoid function&#xff1f; 采⽤Sigmoid 等函数&#xff0c;算激活函数时&#xff08;指数运算&#xff09;&#xff0c;计算量⼤&#xff0c;反向传播求误差梯度时&#xff0c;求导涉及除法和指数运算&#xff0c;计算量…

《VitePress 简易速速上手小册》第2章:Markdown 与页面创建(2024 最新版)

文章目录 2.1 Markdown 基础及扩展2.1.1 基础知识点解析2.1.2 重点案例&#xff1a;技术博客2.1.3 拓展案例 1&#xff1a;食谱分享2.1.4 拓展案例 2&#xff1a;个人旅行日记 2.2 页面结构与布局设计2.2.1 基础知识点解析2.2.2 重点案例&#xff1a;公司官网2.2.3 拓展案例 1&…

软件测试方法_边界值分析法

目录&#xff1a; ①边界值分析法的介绍和概念 ②边界值分析法的原理和思想 ③单缺陷假设和多缺陷假设 ④边界值测试数据类型 ⑤内部边界值分析 ⑥各类边界值测试介绍 ⑦基于边界值分析方法选择测试用例的原则 ⑧边界值分析法的实例分析 1、边界值分析法的介绍和概念 …

力扣94 二叉树的中序遍历 (Java版本) 递归、非递归

文章目录 题目描述递归解法非递归解法 题目描述 给定一个二叉树的根节点 root &#xff0c;返回 它的 中序 遍历 。 示例 1&#xff1a; 输入&#xff1a;root [1,null,2,3] 输出&#xff1a;[1,3,2] 示例 2&#xff1a; 输入&#xff1a;root [] 输出&#xff1a;[] 示…

【大厂AI课学习笔记】【2.2机器学习开发任务实例】(7)特征构造

特征分析之后&#xff0c;就是特征构造。 特征构造第一步 特征构造往往要进行数据的归一化。 在本案例中&#xff0c;我们将所有的数据&#xff0c;将所有特征区间调整为0~1之间。 如上图。 那么&#xff0c;为什么要进行归一化&#xff0c;又如何将数据&#xff0c;调整为…

【安卓基础1】初识Android

&#x1f3c6;作者简介&#xff1a;|康有为| &#xff0c;大四在读&#xff0c;目前在小米安卓实习&#xff0c;毕业入职。 &#x1f3c6;安卓学习资料推荐&#xff1a; 视频&#xff1a;b站搜动脑学院 视频链接 &#xff08;他们的视频后面一部分没再更新&#xff0c;看看前面…

【力扣白嫖日记】1873.计算特殊奖金

前言 练习sql语句&#xff0c;所有题目来自于力扣&#xff08;https://leetcode.cn/problemset/database/&#xff09;的免费数据库练习题。 今日题目&#xff1a; 1873.计算特殊奖金 表&#xff1a;Employees 列名类型employee_idintnamevarcharsalaryint employee_id 是…