从一道面试题说去

简介:     有一道面试题: 给定n个整型数,怎样让这n个数的使用空间最小。     ok,我们都知道在32位的机器下,int类型的数占4个字节,因此n个数总的使用空间应该是4n。


    有一道面试题: 给定n个整型数,怎样让这n个数的使用空间最小。

     ok,我们都知道在32位的机器下,int类型的数占4个字节,因此n个数总的使用空间应该是4n。(64位不做解释)那我们怎么样才能使得n个数字的使用空间最小呢?


    一. 我们先来看一个例子

          假设现在有3个数,1,2,3。

          我们都知道数字最后都是以二进制的方式存储的,我们可以表示出1,2,3的二进制

          1: 0000 0000 0000 0000 0000 0000 0000 0001

          2: 0000 0000 0000 0000 0000 0000 0000 0010

          3: 0000 0000 0000 0000 0000 0000 0000 0011

          正常情况下,要表示1,2,3这三个数,我们必须使用32*3 = 96 bit。我们发现其实这样是非常浪费的,因为对于这三个数来说实际上用到了只是最开始的8个bit,而前面的24个bit都是没有用的。


    二. 我们要怎么压缩,才能使得空间变小呢?

          如果听说过google protobuf的同学就应该马上能知道,压缩的方式了。没错,方法正是protobuf使用的variant的编码方式。

          1. 首先介绍一下什么是protobuf?protobuf是google提出的一种非常强大的结构化数据存储方式,可以通过序列化和反序列化来进行数据操作,详情请走google

          2. 介绍一下protobuf的variant的编码方式

             普通的一个int二进制是32位,4个字节。而protobuf的一个int并不是这么表示,protobuf会把每个字节的8个bit中最高位当做标记位,标记下一个字节是否属于当前这个数。

             比如1,普通的二进制表示是0...0 0000 0001,会占用32位。而protobuf 只要表示成0000 0001,最高位0表示下一个字节不属于当前这个数,因此1只要占用1个字节的空间即可。

          3. variant是怎么进行压缩的呢?

             假设protobuf要存储一个数300(我们只是单纯考虑压缩,不考虑其它存储的方式因为里面涉及到了key-value键值对,感兴趣的同学可以具体去看看google的文档)。

             a.300的二进制如下: 0000 0000 0000 0000 0000 0001 0010 1100

             b. 通过上面我们知道,protobuf的每个字节有一个bit用来标记,有7个bit用来表示值。因为我们对300的二进制从后往前每7个bit进行分割,0101100,0000010,0000000,0000000,0000。去掉后面三组都是0,现在只剩下两组0101100,0000010。 

                 因此一个300的varint表示成1010110000000010。只需要占用2个字节,比原来少了2个字节,因此可以节省空间。

             c.可能有的同学就会问了,既然variant每个字节只能表示7个bit,那就说4个字节最多只有28个bit能表示值,那么当一个数大于等于2^28的时候不是要用5个字节表示?那当n个数都大于2的28次方的时候,不是比4n的空间还大吗?

                没错,这确实是protobuf的一个问题,但是后面我们会有办法来优化这个问题。

         4. protobuf的解压缩方式

            a. 我们了解了variant的压缩方式之后,应该就能明白是怎么解压缩的了。假设我们拿到了一段variant二进制编码101011000000001010000001....,我们从头开始读,当发现当前自己的最高位为0的是就是说明这个数结束了。

            b. 比如我们读到了1010110000000010

                第一步,去标记位: 0101100 0000010

                第二步,交换数据: 0000010 0101100 这一步看不懂的同学请仔细看一些上面的压缩方式。

                第三步,计算: 0000010 0101100 =  2^2 + 2^3 + 2^5 + 2^8 = 300

      

      三. 怎么样做,才能使得空间最小呢?

           别忘了,我们还有一个问题没有解决。就是关于当数值大于2^28次方的时候,使用variant编码方式会使得空间大于4*n。

           ok,假设有3个数2147483645,2147483646,2147483647。正常情况下存储这三个数需要12个字节,如果使用variant每个数需要5个字节,则要15个字节,发现此时并不能减少空间,反而使空间增大。

           在压缩算法里面有一个很经典就是 增量存储。比如这个三个数,我们利用增量存储则可以表示成2147483645,1,1。然后再利用variant存储,则总共只需要5+1+1 = 7个字节,发现此时我们就可以把空间从15压缩到了7,发现收益还是非常可观。

           增量存储是一个非常重要的思想,好比搜索引擎的索引。对于一个商业的索引引擎来说,索引可能是有几百亿,对海量的索引进行压缩存储,收益是非常惊人的。

        

     

目录
相关文章
|
安全 网络安全
Foxmail邮箱提示错误:ssl连接错误,errorCode:5解决方法
Foxmail邮箱提示错误:ssl连接错误,errorCode:5解决方法
5742 0
|
监控 数据库 时序数据库
性能监控之Telegraf+InfluxDB+Grafana window服务器安装使用
【6月更文挑战13天】性能监控之Telegraf+InfluxDB+Grafana window服务器安装使用
674 1
|
9天前
|
人工智能 运维 安全
|
7天前
|
人工智能 异构计算
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
敬请锁定《C位面对面》,洞察通用计算如何在AI时代持续赋能企业创新,助力业务发展!
|
8天前
|
机器学习/深度学习 人工智能 自然语言处理
B站开源IndexTTS2,用极致表现力颠覆听觉体验
在语音合成技术不断演进的背景下,早期版本的IndexTTS虽然在多场景应用中展现出良好的表现,但在情感表达的细腻度与时长控制的精准性方面仍存在提升空间。为了解决这些问题,并进一步推动零样本语音合成在实际场景中的落地能力,B站语音团队对模型架构与训练策略进行了深度优化,推出了全新一代语音合成模型——IndexTTS2 。
671 23
|
7天前
|
人工智能 测试技术 API
智能体(AI Agent)搭建全攻略:从概念到实践的终极指南
在人工智能浪潮中,智能体(AI Agent)正成为变革性技术。它们具备自主决策、环境感知、任务执行等能力,广泛应用于日常任务与商业流程。本文详解智能体概念、架构及七步搭建指南,助你打造专属智能体,迎接智能自动化新时代。
|
14天前
|
人工智能 JavaScript 测试技术
Qwen3-Coder入门教程|10分钟搞定安装配置
Qwen3-Coder 挑战赛简介:无论你是编程小白还是办公达人,都能通过本教程快速上手 Qwen-Code CLI,利用 AI 轻松实现代码编写、文档处理等任务。内容涵盖 API 配置、CLI 安装及多种实用案例,助你提升效率,体验智能编码的乐趣。
1097 110