专栏:Java数据结构秘籍

个人主页:手握风云

目录

一、位图

1.1. 概念

1.2. 面试题

1.3. 位图的实现

1.4. 位图的应用


一、位图

1.1. 概念

        在数据结构中,位图(也称为位数组、位向量或位集)是一种紧凑的方式来表示一组布尔值(真/假、1/0)。它本质上是一个数组,其中每个元素代表一个位,该位的位置通常对应于一个标识符或索引。适用于海量数据,整数,数据无重复的场景。

1.2. 面试题

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

        解法:

  1. 遍历,时间复杂度O(n)
  2. 排序+二分查找,时间复杂度O(nlogn)+O(logn)。10亿个byte大约是1G,10亿个整数大约是4G,40亿个整数大约就是16G,很明显内存不够

        这时我们就可以使用位图来解决上述问题。我们知道一个整数是32个比特位,那么每一个比特位就可以存储不同的数字,0代表没出现过,1代表出现过。那我们就可以根据一组数据的某种关系映射到里面。

        如下图所示,我们就可以以8个比特位为一组,每个数据进行/8的操作,然后将其储存在比特位的下标里面。

        这样的话40亿个整数只需大约476MB就可以解决。

1.3. 位图的实现

        在Java的集合框架中,也有BitSet类。

import java.util.BitSet;public class Test {public static void main(String[] args) {BitSet bitSet = new BitSet();// 设置位bitSet.set(0);bitSet.set(2);bitSet.set(4);// 获取BitSet的大小System.out.println(bitSet.size());// 查询位的状态System.out.println(bitSet.get(0));System.out.println(bitSet.get(1));System.out.println(bitSet.get(2));// 清除位bitSet.clear(2);System.out.println(bitSet.get(2));}
}

public class MyBitSet {public byte[] elem;public int usedSize;public MyBitSet(byte[] elem) {this.elem = new byte[1];}/*** 有可能多给一个字节,但是无所谓* @param n 多少位*/public MyBitSet(int n) {this.elem = new byte[n / 8 + 1];}/*** 设置某一位为1,证明数据出现过* @param val 查找的数据*/public void set(int val) {}/**** @param val 输入的数据* @return 判断当前位是不是1*/public boolean get(int val) {return false;}/*** 将对应位置置为0* @param val 输入的位数*/public void reSet(int val) {}// 获取当前已经使用的位数public int getUsedSize() {return usedSize;}
}

        我们先来看设置位方法。如果输入的数据小于0,需要抛出下标越界的异常。对于输入的数据,我们既要计算出需要对应在字节数组中的哪个字节,还要计算出在字节中的哪个bit位。之后我们还需要进行将对应的比特位下标置为1,并且不能改变其它位置的值。比如,我们要设置2位置为1,先将1左移2位,再进行按位或操作。

public void set(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] |= (1 << bitIndex);usedSize++;
}

        对于get()方法,我们先左移对应的比特位,然后进行按位与的操作,如果结果不是0,说明该位置为1。

public boolean get(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;return (elem[arrayIndex] & (1 << bitIndex)) != 0;
}

        对于reSet()方法,我们先假设原来这个地方为0,一进行按位与操作,就会将其变成1,所以我们先左移然后按位取反再进行安=按位与。

public void reSet(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] &= ~(1 << bitIndex);usedSize--;
}
  • 测试结果
public static void main(String[] args) {int[] array = {1, 3, 7, 4, 12, 16, 19, 13, 22, 18};MyBitSet bitSet = new MyBitSet(22);for (int i = 0; i < array.length; i++) {bitSet.set(array[i]);}System.out.println(bitSet.get(7));System.out.println(bitSet.get(5));System.out.println(bitSet.get(50));
}

        出现异常正是因为没有进行扩容,50 / 8结果是6,就会产生越界异常。

        完整代码实现:

import java.util.Arrays;public class MyBitSet {public byte[] elem;public int usedSize;public MyBitSet(byte[] elem) {this.elem = new byte[1];}/*** 有可能多给一个字节,但是无所谓* @param n 多少位*/public MyBitSet(int n) {this.elem = new byte[n / 8 + 1];}/*** 设置某一位为1,证明数据出现过* @param val 查找的数据*/public void set(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;// 扩容if (arrayIndex > elem.length - 1) {elem = Arrays.copyOf(elem, arrayIndex + 1);}int bitIndex = val % 8;elem[arrayIndex] |= (1 << bitIndex);usedSize++;}/**** @param val 输入的数据* @return 判断当前位是不是1*/public boolean get(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;if (arrayIndex >= elem.length) {return false;}return (elem[arrayIndex] & (1 << bitIndex)) != 0;}/*** 将对应位置置为0* @param val 输入的位数*/public void reSet(int val) {if (val < 0) {throw new IndexOutOfBoundsException();}int arrayIndex = val / 8;int bitIndex = val % 8;elem[arrayIndex] &= ~(1 << bitIndex);usedSize--;}// 获取当前已经使用的位数public int getUsedSize() {return usedSize;}public static void main(String[] args) {int[] array = {1, 3, 7, 4, 12, 16, 19, 13, 22, 18};MyBitSet bitSet = new MyBitSet(22);for (int i = 0; i < array.length; i++) {bitSet.set(array[i]);}System.out.println(bitSet.get(7));System.out.println(bitSet.get(5));System.out.println(bitSet.get(50));}
}

1.4. 位图的应用

  1. 高效存储与查询大量布尔状态;
  2. 集合运算(交集、并集、差集);
  3. 位图排序(适合范围已知的整数排序)
  4. 去重与计数;
  5. 布隆过滤器(Bloom Filter)底层实现

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

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

相关文章

芯科科技即将重磅亮相IOTE 2025深圳物联网展,以全面的无线技术及生态覆盖赋能万物智联

作为低功耗无线连接领域的创新性领导厂商&#xff0c;Silicon Labs&#xff08;亦称“芯科科技”&#xff09;将于8月27至29日携其最前沿的人工智能&#xff08;AI&#xff09;和物联网&#xff08;IoT&#xff09;解决方案在深圳举办的IOTE 2025国际物联网展中盛大展出。这场亚…

Linux上安装多个JDK版本,需要配置环境变量吗

简短回答&#xff1a;不需要同时配置多个 JDK 的 JAVA_HOME 和 PATH&#xff0c;但你可以安装多个版本&#xff0c;并通过灵活的方式在它们之间切换。 文章目录✅ 正确做法&#xff1a;安装多个 JDK&#xff0c;但只让一个生效&#xff08;通过环境变量或 alternatives&#xf…

MySQL有哪些高可用方案

大家好&#xff0c;我是锋哥。今天分享关于【MySQL有哪些高可用方案】面试题。希望对大家有帮助&#xff1b; MySQL有哪些高可用方案? 超硬核AI学习资料&#xff0c;现在永久免费了&#xff01; MySQL 高可用方案是指确保 MySQL 数据库在面对硬件故障、网络故障、负载过重等…

【Windows】Windows平台基于加速地址安装vcpkg并集成到Visual Studio 2017

基础运行环境 启动&#xff1a; 适用于 VS 2017 的 x64 本机工具命令提示 ninja 下载压缩包 https://gh-proxy.com/https:/github.com/ninja-build/ninja/releases/download/v1.13.1/ninja-win.zip 直接解压到c:/Windows (无需配置环境变量) CMake 下载安装包 https://gh-proxy…

LLMs之MCP:Chrome MCP的简介、安装和使用方法、案例应用之详细攻略

LLMs之MCP&#xff1a;Chrome MCP的简介、安装和使用方法、案例应用之详细攻略 目录 Chrome MCP的简介 1、特点 2、与类似项目的比较 Chrome MCP的安装和使用方法 1、安装 2、使用方法 加载 Chrome 扩展 与 MCP 协议客户端一起使用 使用 STDIO 连接&#xff08;替代方…

【Java EE】多线程-初阶 synchronized 关键字 - 监视器锁 monitor lock

synchronized 关键字 - 监视器锁 monitor lock5. synchronized 关键字 - 监视器锁 monitor lock5.1 synchronized 的特性5.2 synchronized 使⽤⽰例5.3 Java 标准库中的线程安全类本节⽬标• 掌握 synchronized关键字5. synchronized 关键字 - 监视器锁 monitor lock &#xf…

Java多线程:从基础到实战

引言多线程是Java并发编程的核心技术之一&#xff0c;广泛应用于服务器开发、数据处理、实时系统等领域。通过多线程&#xff0c;程序可以充分利用CPU资源&#xff0c;提高执行效率&#xff0c;同时处理多个任务。本文将从多线程的基本概念、实现方式、线程状态、同步与通信到常…

list集合可以一边遍历一遍修改元素吗?

今天看来一下Java中list集合部分的八股&#xff0c;发现了一个以前没注意过的问题&#xff0c;记录一下list可以一边遍历一边修改元素吗&#xff1f;答&#xff1a;在 Java 中&#xff0c;List在遍历过程中是否可以修改元素取决于遍历方式和具体的List实现类。①&#xff1a;对…

Infusing fine-grained visual knowledge to Vision-Language Models

Infusing fine-grained visual knowledge to Vision-Language Models Authors: Nikolaos-Antonios Ypsilantis, Kaifeng Chen, Andr Araujo, Ondřej Chum Deep-Dive Summary: 视觉-语言模型中注入细粒度视觉知识 摘要 大规模对比预训练产生了强大的视觉-语言模型&#xf…

RK3576赋能无人机巡检:多路视频+AI识别引领智能化变革

随着工业巡检任务的复杂度不断提升&#xff0c;无人机逐渐取代传统人工&#xff0c;成为电力、能源、林业、农业等行业的“高空作业主力”。然而&#xff0c;巡检并非简单的拍摄和回放&#xff0c;它要求无人机实时采集多路画面、快速分析异常&#xff0c;并稳定回传数据。这对…

ollama Modelfile 文件生成

输入 根据如下TEMPLATE和params写一个modelfile文件&#xff0c;TEMPLATE为&#xff1a;{{- $lastUserIdx : -1 -}} {{- range $idx, $msg : .Messages -}} {{- if eq $msg.Role “user” }}{{ $lastUserIdx $idx }}{{ end -}} {{- end }} {{- if or .System .Tools }}<|i…

关联规则挖掘2:FP-growth算法(Frequent Pattern Growth,频繁模式增长)

目录 一、核心思想&#xff1a;一个形象的比喻 二、核心思想的具体拆解 步骤一&#xff1a;构建FP-tree&#xff08;频繁模式树&#xff09; 步骤二&#xff1a;从FP-tree中挖掘频繁项集 为什么这很高效&#xff1f; 三、总结 核心思想与优势 适用场景与缺点 四、例题…

在IDEA中DEBUG调试时查看MyBatis-Plus动态生成的SQL语句

在IDEA中DEBUG调试时查看MyBatis-Plus动态生成的SQL语句前言&#xff1a;动态SQL调试的痛与解决方案一、准备工作&#xff1a;调试前的检查清单二、基础方法&#xff1a;SqlSessionTemplate断点调试步骤1&#xff1a;定位SqlSessionTemplate类步骤2&#xff1a;在invoke方法上设…

Linux 文本处理三剑客:awk、grep、sed 完全指南

Linux 文本处理三剑客&#xff1a;awk、grep、sed 完全指南 1. 概述 Linux 系统提供了三个强大的文本处理工具&#xff1a;awk、grep 和 sed&#xff0c;它们各有所长&#xff0c;结合使用可以高效地处理文本数据。 awk&#xff1a;擅长文本分析和格式化输出&#xff0c;是一…

pyecharts可视化图表组合组件_Grid:打造专业数据仪表盘

pyecharts可视化图表组合组件_Grid&#xff1a;打造专业数据仪表盘 目录pyecharts可视化图表组合组件_Grid&#xff1a;打造专业数据仪表盘引言图表1&#xff1a;Grid-Overlap-多X/Y轴示例代码解析1. 图表创建2. 多轴配置3. 图表重叠4. Grid布局效果与应用图表2&#xff1a;Gri…

【电气工程学习】

三极管中&#xff1a;集电极C,基极B&#xff0c;发射极E接线&#xff1a;棕正蓝负黑信号NPN开关输出的是我们的0V,也叫低电平PNP开关输出的是24V,也就是高电平&#xff08;NPN开关导通时&#xff0c;相当于把输出端“拉”到0V&#xff08;低电平&#xff09;&#xff0c;称为“…

【嵌入式】CAN通信

CAN 总线最初由博世于1980年代为汽车行业开发&#xff0c;能够简化复杂的布线网络&#xff0c;还确保可靠和安全的数据传输。 1.CAN技术解释 CAN网络中的每个节点&#xff0c;都是平等的&#xff0c;没有主次之分&#xff0c;这一点和SPI和I2C不同。每个节点都可以在需要的时…

Apache ShenYu网关与Nacos的关联及如何配合使用

Apache ShenYu 网关与 Nacos 之间的关系可以概括为 “协作互补”:Nacos 作为 服务注册与配置中心,为 ShenYu 提供动态的服务发现和配置管理能力,而 ShenYu 作为 流量网关,依赖 Nacos 实现路由信息的动态更新和实时生效。以下是详细解析: 1. 核心关系图解 拉取服务列表/路…

【CPP】一个CPP的Library(libXXXcore)和测试程序XXX_main的Demo

一个CPP的Library和测试程序Demo 1. 思路描述 目录结构 总控CMakeList.txt文件 2. Library代码实现 2.1 XXXLib.hpp文件(对外的接口定义文件)和XXXLib.cpp文件 2.1.1 XXXLib.hpp文件 2.1.2 XXXLib.cpp文件 2.2 CXXXLibApi.hpp文件和CXXXLibApi.cpp文件(内部的API基类) 2.2.1 CX…

【YashanDB认证】学习YashanDB的探索之路:从入门到实践

在国产数据库蓬勃发展的浪潮中&#xff0c;选择了YashanDB作为技术学习的切入点。这不仅让我深入了解了数据库的核心技术&#xff0c;也让我深刻体会到国产数据库在性能、可靠性和生态适配上的创新价值。以下是我在学习YashanDB过程中的经验与感悟。 一、YashanDB基础介绍 Ya…