[Go版]算法通关村第十五关青铜——用4KB内存寻找重复元素

目录

海量数据中,此时普通的数组、链表、Hash、树等等结构有无效了 ,因为内存空间放不下了。而常规的递归、排序,回溯、贪心和动态规划等思想也无效了,因为执行都会超时,必须另外想办法。这类问题该如何下手呢?这里介绍三种非常典型的思路:

  1. 使用位存储,使用位存储最大的好处是占用的空间是简单存整数的1/8。例如一个40亿的整数数组,如果用整数存储需要16GB左右的空间,而如果使用位存储,就可以用2GB的空间,这样很多问题就能够解决了。

  2. 如果文件实在太大 ,无法在内存中放下,则需要考虑将大文件分成若干小块,先处理每个块,最后再逐步得到想要的结果,这种方式也叫做外部排序。这样需要遍历全部序列至少两次,是典型的用时间换空间的方法

  3. 如果在超大数据中找第K大、第K小,K个最大、K个最小,则特别适合使用堆来做。而且将超大数据换成流数据也可以,而且几乎是唯一的方式,口诀就是“查小用大堆,查大用小堆”。
    常识补充:10亿 ≈ 1G、100万 ≈ 1M

题目:用4KB内存寻找重复元素

给定一个数组,包含从1到N的整数,N最大为32000,数组可能还有重复值,且N的取值不定,若只有4KB的内存可用,该如何打印数组中所有重复元素。

思路分析:使用位存储

如何存储这32000个整数?

常规思路分析:32000个整数,整数用int表示,一个int占用4个字节(byte),32000个整数所需内存就是 :

32000 * 4 = 128000(byte)
32000 * 4 / 1024 = 125(KB)
125(KB) > 4(KB)	//可见,已经超过题目要求的4KB内存要求。

下面我们使用位存储的方式:1个字节(byte)=8位(bit),32000个正数用32000个位就是:

32000 / 8 = 4000(byte)
32000 / 8 / 1024 = 3.9(KB)
3.9(KB)< 4(KB)	//如此,就满足题意,使用了4KB就能存储32000个元素

每个整数对应在位图中的存储状态举例

原数据:				1  2  3  4  5  6  7  8  9 10 11 12 13 14 15 16 17 18  ...
该值在位图中的索引值:	0  0  0  0  0  0  0  1  1  1  1  1  1  1  1  2  2  2  ... 
该值在位图中的偏移量:	1  2  3  4  5  6  7  0  1  2  3  4  5  6  7  0  1  2  ...1 对应的位图值,和二进制值为:byteMap[0]	00000010
2 对应的位图值,和二进制值为:byteMap[0]	00000100
3 对应的位图值,和二进制值为:byteMap[0]	00001000
4 对应的位图值,和二进制值为:byteMap[0]	00010000
5 对应的位图值,和二进制值为:byteMap[0]	00100000
6 对应的位图值,和二进制值为:byteMap[0]	01000000
7 对应的位图值,和二进制值为:byteMap[0]	10000000
8 对应的位图值,和二进制值为:byteMap[1]	00000001
9 对应的位图值,和二进制值为:byteMap[1]	00000010
...

如何判断是重复的?

既然我们用一个位(bit)代表一个数值,那么该位的两种状态0或1,就可以用于判断该值是否存在。
例如:字节00001101表示以下情况:

  • 第 0 位(最低位)为 1,表示数字 1 出现过。
  • 第 1 位为 0,表示数字 2 没有出现过。
  • 第 2 位为 1,表示数字 3 出现过。
  • 第 3 位为 1,表示数字 4 出现过。
  • 后续位为 0,表示数字 5 到 8 都没有出现过。
mark := 1 << offset	//offset 就是偏移量
if (bitmap[index] & mask) != 0 {// 位已经被设置,说明数字出现过
}
bitmap[index] |= mask	//设置该位值为1

具体的步骤

位图(Bitmap)是一种数据结构,用于表示一组元素的状态或属性,通常用二进制位来表示,每个位代表一种状态或属性。在计算机科学中,位图被广泛用于各种应用,如图像处理、数据压缩、数据库索引等。

  1. 初始化位图:由于N最大是32000,可以是哦用一个长度为32000/8=4000的位图,每个位可以表示一个整数。
  2. 遍历数组,对于数组中的每个元素:
    • 计算x在位图中的索引和位偏移。例如:x=5,则索引为5/8=0,位偏移为5%8=5。
    • 检查位图的索引位置是否已经被标记。
      • 如果未被标记,则将其标记为已访问;
      • 如果已经被标记,则说明x是重复的,打印x。
  3. 打印重复元素。

复杂度:时间复杂度 O ( n ) O(n) O(n)、空间复杂度 O ( 1 ) O(1) O(1)

Go代码

源码地址: GitHub-golang版本(含单元测试代码)

func FindDuplicatesIn32000(arr []int) (duplicate []int) {N := 32000bitmap := make([]byte, N/8+1)for _, num := range arr {// 计算 num 在 bitmap 中的索引// index := num / 8index := num >> 3// 计算 num 在 bitmap 中的偏移量offset := num % 8mark := byte(1 << offset)if bitmap[index]&mark != 0 {duplicate = append(duplicate, num)} else {bitmap[index] |= mark}}return
}

或者

func FindDuplicatesIn32000(arr []int) (duplicate []int) {N := 32000// 或者这里不用+1,只要索引是base0的即可bitmap := make([]int, N/32)for _, num := range arr {num0 := num - 1 //base0开始index := num0 / 32offset := num0 % 32mark := 1 << offsetif bitmap[index]&mark != 0 {duplicate = append(duplicate, num)} else {bitmap[index] |= mark}}return
}

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

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

相关文章

对刚毕业想从事程序员行业的大学生的忠告

刚毕业的大学生&#xff0c;都怀揣着雄心壮志&#xff0c;出人头地 工作一两年后&#xff0c;技术提升的飞快&#xff0c;不断学习和使用新技术 工作三四年后&#xff0c;每个月的工资也以肉眼可见的速度提升着&#xff0c;工资开始以万为单位计算 工作五六年后&#xff0c;…

Spring Boot 中 Nacos 配置中心使用实战

官方参考文档 https://nacos.io/zh-cn/docs/quick-start-spring-boot.html 本人实践 1、新建一个spring boot项目 我的spirngboot版本为2.5.6 2、添加一下依赖 <dependency><groupId>org.springframework.boot</groupId><artifactId>spring-boot-…

MySQL事物和存储引擎

事务 一、MySQL事务的概念 事务是一种机制、一个操作序列&#xff0c;包含了一组数据库操作命令&#xff0c;并且把所有的命令作为一个整体一起向系统提交或撤销操作请求&#xff0c;即这一组数据库命令要么都执行&#xff0c;要么都不执行。 事务是一个不可分割的工作逻辑单…

无涯教程-JavaScript - CUBEMEMBERPROPERTY函数

描述 CUBEMEMBERPROPERTY函数从多维数据集返回成员属性的值。使用此函数可以验证多维数据集中是否存在成员名称,并返回该成员的指定属性。 语法 CUBEMEMBERPROPERTY (connection, member_expression, property)争论 Argument描述Required/OptionalconnectionName of the co…

JavaScript基础语法03——JS注释、结束符

哈喽&#xff0c;大家好&#xff0c;我是雷工&#xff01; 今天继续学习JavaScript基础语法知识&#xff0c;注释和结束符&#xff0c;以下为学习笔记。 一、JavaScript注释 JavaScript注释有什么作用&#xff1f; JavaScript注释可以提高代码的可读性&#xff0c;能够帮助像…

arduino仿真 SimulIDE1.0仿真器

SimulIDE 是一个开源的电子电路模拟器&#xff0c;支持模拟各种电子元器件的行为&#xff0c;可以帮助电子工程师和爱好者进行电路设计和测试。以下是 SimulIDE 的安装和使用说明&#xff1a; 安装 SimulIDE SimulIDE 可以在 Windows、Linux 和 Mac OS X 等操作系统上安装。您…

计算机视觉中常用的角点检测算法及其作用

角点检测是计算机视觉中的重要任务&#xff0c;用于识别图像中的角点或关键点。以下是一些常用的角点检测算法&#xff1a; Harris角点检测&#xff1a;Harris角点检测是一种经典的角点检测算法&#xff0c;它通过计算图像中每个像素的角点响应函数来检测角点。Harris角点检测对…

零知识证明(zk-SNARK)(二)

From Computational Problem to zk-SNARK 本部分就是将计算难题转换为多项式&#xff0c;然后使用zk-SNARK。 &#xff08;注&#xff1a;以下用 P&#xff0c;V 替代 Prover&#xff0c;Verifier&#xff09; 计算难题->R1CS R1CS(Rank-1 Constraint System)是一种能够…

js 基础 (ES 模块)

ES 模块语法 1、模块化的背景 JavaScript 程序本来很小——在早期&#xff0c;它们大多被用来执行独立的脚本任务&#xff0c;在你的 web 页面需要的地方提供一定交互&#xff0c;所以一般不需要多大的脚本。过了几年&#xff0c;我们现在有了运行大量 JavaScript 脚本的复杂…

jvm的内存区域

JVM 内存分为线程私有区和线程共享区&#xff0c;其中方法区和堆是线程共享区&#xff0c;虚拟机栈、本地方法栈和程序计数器是线程隔离的数据区。 1&#xff09;程序计数器 程序计数器&#xff08;Program Counter Register&#xff09;也被称为 PC 寄存器&#xff0c;是一块…

国产IDE如何获得捐赠和风险投资

有人在开发VB6 脚本工具&#xff0c;有人在开发VB6的插件&#xff0c;把VB6变成VSCODE界面模式&#xff0c;再加上NUGET&#xff0c;NPM等包管理器原理的在线组件、源码下载功能。 还有TWINBASIC几乎80%代替了VB6&#xff0c;radbasic一直封闭&#xff0c;听说也收到了不少众筹…

Programming abstractions in C阅读笔记:p139-p143

《Programming Abstractions In C》学习第55天&#xff0c;p139-p140&#xff0c;总结如下&#xff1a; 一、技术总结 1.文件I/O操作 文件I/O操作可以分为一下这些步骤&#xff1a; (1)声明文件指针对象。 File *infile;(2)打开文件 fopen()。打开文件的模式有“r”, “w…

Android Camera开发入门(4):USB/UVC Camera的使用

Android Camera开发入门(4):USB/UVC Camera的使用 本文基于开源项目https://github.com/saki4510t/UVCCamera之上进行二次封装和使用 在前几篇文章中,我们介绍了Camera到CameraX的基础功能应用,同时附上了相关代码,需要的源码的大佬们可以滑到最底部获取。 本篇我们一起…

基于RabbitMQ的模拟消息队列之二---创建项目及核心类

一、创建项目 创建一个SpringBoot项目&#xff0c;环境&#xff1a;JDK8&#xff0c;添加依赖&#xff1a;Spring Web、MyBatis FrameWork(最主要&#xff09; 二、创建核心类 1.项目分层 2.核心类 在mqserver包中添加一个包&#xff0c;名字为core&#xff0c;表示核心类…

MIPI D-PHY的初始化(MIPI Alliance Xilinx)

DPHY的基本介绍及使用已有很多文章&#xff0c;基本是基于《MIPI Alliance Specification for D-PHY 》的内容&#xff0c;学习时也以此为准&#xff0c;可参考CSDN上的文章。着重讲述MIPI D-PHY的初始化部分 1 D-PHY的功能及使用 下面的文章讲的不错&#xff0c;既有理论&…

Oracle drop删除表如何恢复

摘要&#xff1a; 在 Oracle 数据库管理中&#xff0c;DROP 命令的误操作可能导致数据不可挽回的丢失。然而&#xff0c;Oracle 提供了回收站&#xff08;recycle bin&#xff09;功能&#xff0c;允许用户在删除对象后的一段时间内恢复它们。本文将介绍如何查询、启用和管理回…

iOS swift5 扫描二维码

文章目录 1.生成二维码图片2.扫描二维码&#xff08;含上下扫描动画&#xff09;2.1 记得在info.plist中添加相机权限描述 1.生成二维码图片 import UIKit import CoreImagefunc generateQRCode(from string: String) -> UIImage? {let data string.data(using: String.En…

重要变更 | Hugging Face Hub 的 Git 操作不再支持使用密码验证

在 Hugging Face&#xff0c;我们一直致力于提升服务安全性&#xff0c;因此&#xff0c;我们将修改 Hugging Face Hub 的 Git 交互认证方式。 从 2023 年 10 月 1 日 开始&#xff0c;我们将不再接受密码作为命令行 Git 操作的认证方式。我们推荐使用更安全的认证方法&#xf…

可后悔贪心 -- 解题报告

反悔贪心_Elicsyd的博客-CSDN博客 感觉普通贪心是每一个维度都是平等的&#xff0c;没有优先级。而可后悔贪心是存在某个维度是不可变的&#xff0c;不能直接用排序或者堆进行维护&#xff0c;常常需要经过某种处理&#xff0c;通过挖掘出题目中关于不可变维度的特殊性质&…

架构:C4 Model

概念 C4说穿了就是几个要素&#xff1a;关系——带箭头的线、元素——方块和角色、关系描述——线上的文字、元素的描述——方块和角色里的文字、元素的标记——方块和角色的颜色、虚线框&#xff08;在C4里面虚线框的表达力被极大的限制了&#xff0c;我觉得可以给虚线框更大…