如何使用1M的内存排序100万个8位数

今天看到这篇文章,颇为震撼,感叹算法之“神通”。借助于合适的算法可以完成看似不可能的事情。

最早这个问题是在Stack Overflow网站上面给出的(Sorting numbers in RAM):

题目:

提供一个1M的ROM和1M的RAM,一个输入流和一个输出流。程序代码最终烧录在1M的ROM中,程序可以使用1M的RAM进行运算。输入流中依次输入100万个8位的整数,要求输出流中输出这100万个数排序后的结果。

已经可以搜索到很多解法了,今天看到一个国外的程序员的分析,觉得很有趣,想把他的分析过程简单转在这里。简单一看,根本不可能,100万个8位数无论如何也不能在1M的内存里装下。排序过程是利用归并排序,效率较高。最难的地方是在如何将排序后的100万个数字存下来。换一种思路,不一定要存下每一个数字本身,因为数字都已经排序了,那么相邻两个数字之间的差值是非常小的,如果在极端的情况下,两个数字之间的差值非常大,那么必然会有更多量的相邻数字之间的差值更小,因此存下所有的100万个数字的差值需要的空间是可以估算的。

平均每一个差值的大小为:10^8/100万 = 100,100需要7个bit位来表示,因此共需要100万×7 = 875, 000 字节,不到1M的空间,但是还有很多大于128的数值需要编码,这样有一些数值的编码大于7个bit。因此,接下来的问题是如何编码这100万个差值,能尽可能压缩空间,作者举出了算数编码来解决这一问题,选择一种简单的编码规则,即:看第一个bit位,如果是0,则后6个bit位表示数值,如果是1,则表示差值为64,继续读取后一位,如果仍然为1,则差值继续累加1,直到读到0,然后读取后面的6个bit,这样可以表示所有可能出现的值,这样下来,最终计算出所需要的内存为1070312.5bytes,仍然大于1M。

最终采用了一个针对该问题的哈夫曼编码解决。算数编码看懂了,哈夫曼编码也似乎看明白了,但是怎样运用到解决本问题中,还不是太明白。同时作者也给出了339行的解决问题的实战代码。

版权声明:欢迎转载,希望在你转载的同时,添加原文地址,谢谢配合

时间: 2024-10-10 03:06:31

如何使用1M的内存排序100万个8位数的相关文章

100万个数据,数据值在0~65535之间,请用尽可能少的内存和最快的速度从小到大排序

场景说明:100万个数据,数据值在0~65535之间,请用尽可能少的内存和最快的速度从小到大排序 voidsort(int* array, int n) { //n的值在100万左右 //你的实现 } 我们首先观察到所有的数据已经保存到了array数组中,现在我们需要做的就是将数组中的元素排序.现在我们把数组中的元素提取出来比如是3,然后我们提取出数组下标是3的元素,保存到临时空间,通过负数来计算个数: void sort(int* array, int n) {     int tmp=0;

100万并发连接服务器笔记之Java Netty处理1M连接会怎么样

前言 每一种该语言在某些极限情况下的表现一般都不太一样,那么我常用的Java语言,在达到100万个并发连接情况下,会怎么样呢,有些好奇,更有些期盼.  这次使用经常使用的顺手的     netty NIO框架(netty-3.6.5.Final),封装的很好,接口很全面,就像它现在的域名   netty.io,专注于网络IO.  整个过程没有什么技术含量,浅显分析过就更显得有些枯燥无聊,准备好,硬着头皮吧. 测试服务器配置 运行在VMWare Workstation 9中,64位Centos 6

100万连接测试资料整理

设置相关脚本: 默认: $cat /proc/sys/net/ipv4/ip_local_port_range 32768    61000 $cat setting.sh #/bin/bash # modify backlog, meanwhile change listen function to 1024, default 128 # echo “1024" > /proc/sys/net/core/somaxconn sysctl -w net.core.somaxconn = 1

Stackful 协程库 libgo(单机100万协程)

libgo 是一个使用 C++ 编写的协作式调度的stackful协程库, 同时也是一个强大的并行编程库. 设计之初是为高并发分布式Linux服务端程序开发提供底层框架支持,可以让链接进程序的同步的第三方库变为异步库,不影响逻辑的前提下提升其性能. 目前支持两个平台: Linux (GCC 4.8+) Windows (Win7.Win8.Win10 x86 and x64 使用VS2013/2015编译) 使用libgo编写并行程序,即可以像golang一样开发迅速且逻辑简洁,又有C++原生的

SQLServer如何快速生成100万条不重复的随机8位数字

最近在论坛看到有人问,如何快速生成100万不重复的8位编号,对于这个问题,有几点是需要注意的: 1.    如何生成8位随机数,生成的数越随机,重复的可能性当然越小 2.    控制不重复 3.    考虑性能 针对这个问题,我写了如下的示例来解决,希望能为有这类需求的人提供指导 */ USE tempdb GO --创建测试表 CREATE TABLE tb(id char(8)) --创建用于自动过滤重复值的唯一索引 CREATE UNIQUE INDEX IX_tb ON tb(id) W

极限挑战—C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码)

原文:极限挑战-C#100万条数据导入SQL SERVER数据库仅用4秒 (附源码) 实际工作中有时候需要把大量数据导入数据库,然后用于各种程序计算,本实验将使用5中方法完成这个过程,并详细记录各种方法所耗费的时间. 本实验中所用到工具为VS2008和SQL SERVER 2000.SQL SERVER 2008,分别使用5中方法将100万条数据导入SQL 2000与SQL 2008中,实验环境是DELL 2850双2.0GCPU,2G内存的服务器.感兴趣的朋友可以下载源代码自己验证一下所用时间

给你100万条数据的一张表,你将如何查询优化?

1.两种查询引擎查询速度(myIsam 引擎 ) InnoDB 中不保存表的具体行数,也就是说,执行select count(*) from table时,InnoDB要扫描一遍整个表来计算有多少行. MyISAM只要简单的读出保存好的行数即可. 注意的是,当count(*)语句包含 where条件时,两种表的操作有些不同,InnoDB类型的表用count(*)或者count(主键),加上where col 条件.其中col列是表的主键之外的其他具有唯一约束索引的列.这样查询时速度会很快.就是可

python 统计MySQL大于100万的表

一.需求分析 线上的MySQL服务器,最近有很多慢查询.需要统计出行数大于100万的表,进行统一优化. 需要筛选出符合条件的表,统计到excel中,格式如下: 库名 表名 行数 db1 users 1234567 二.统计表的行数 统计表的行数,有2中方法: 1. 通过查询mysql的information_schema数据库中INFODB_SYS_TABLESTATS表,它记录了innodb类型每个表大致的数据行数 2. select count(1) from 库名.表名 下面来分析一下这2

草根站长如何挣到人生第一个100万

导读:财神的文章总有种醍醐灌顶的感觉,读完本文能在思维上和视野上有所拓展,但我知道文章标题党了,本文你并不能赚到人生的100万,但本文也许会改变你的建站思路. 每 个做网络的人其实都有过想暴富的心态,包括我自己当时想做网络就是因为受到朋友和网上一些大神们的影响.看到别人几千几百万的赚真的是太吸引了.说实话, 大部分人都是因为这样的心态开始做网络的.当然也有一些是因为兴趣爱好,或者想搞点兼职帮补开支的.但是基本90%的站长都做过创富梦. 特 别是我们看多了马云, 史玉柱,李彦宏,马化腾等他们被吹嘘