我有一台有1mb内存的电脑,没有其他本地存储。我必须使用它通过TCP连接接受100万个8位十进制数字,对它们进行排序,然后通过另一个TCP连接发送排序的列表。

数字列表可能包含重复的,我不能丢弃。代码将放在ROM中,所以我不需要从1 MB中减去我的代码的大小。我已经有了驱动以太网端口和处理TCP/IP连接的代码,它需要2 KB的状态数据,包括1 KB的缓冲区,代码将通过它读取和写入数据。这个问题有解决办法吗?

问答来源:

slashdot.org

cleaton.net


当前回答

我在这里的建议很大程度上归功于Dan的解决方案

首先,我假设解决方案必须处理所有可能的输入列表。我认为流行的答案并没有做出这样的假设(在我看来这是一个巨大的错误)。

众所周知,任何形式的无损压缩都不会减小所有输入的大小。

所有流行的答案都假设它们能够有效地应用压缩来允许它们有额外的空间。事实上,一个足够大的额外空间块,以未压缩的形式保存他们部分完成的列表的一部分,并允许他们执行排序操作。这只是一个糟糕的假设。

对于这样的解决方案,任何了解如何进行压缩的人都能够设计一些不能很好地压缩该方案的输入数据,并且“解决方案”很可能会由于空间不足而崩溃。

相反,我采用数学方法。我们可能的输出是所有长度为LEN的列表,由0..MAX范围内的元素组成。这里LEN是1,000,000,MAX是100,000,000。

对于任意的LEN和MAX,编码此状态所需的比特数为:

Log2(MAX multichoice LEN)

因此,对于我们的数字,一旦我们完成了接收和排序,我们将需要至少Log2(100,000,000 MC 1,000,000)位来存储我们的结果,以一种能够唯一区分所有可能输出的方式。

这是~= 988kb。所以我们有足够的空间来存放结果。从这个角度来看,这是可能的。

[删除了无意义的漫谈,现在有更好的例子…]

最好的答案在这里。

另一个很好的答案是这里,它基本上使用插入排序作为函数,将列表扩展为一个元素(缓冲一些元素并进行预先排序,以允许一次插入多个元素,节省一些时间)。使用一个很好的压缩状态编码,7位增量的桶

其他回答

你试过转换成十六进制吗?

我可以看到前后文件大小都有了很大的减小;然后,用自由空间分步计算。也许,再次转换为dec, order,十六进制,另一个块,转换为dec, order…

对不起. .我不知道是否可行

# for i in {1..10000};do echo $(od -N1 -An -i /dev/urandom) ; done > 10000numbers
# for i in $(cat 10000numbers ); do printf '%x\n' $i; done > 10000numbers_hex
# ls -lah total 100K
drwxr-xr-x  2 diego diego 4,0K oct 22 22:32 .
drwx------ 39 diego diego  12K oct 22 22:31 ..
-rw-r--r--  1 diego diego  29K oct 22 22:33 10000numbers_hex
-rw-r--r--  1 diego diego  35K oct 22 22:31 10000numbers

If it is possible to read the input file more than once (your problem statement doesn't say it can't), the following should work. It is described in Benchley's book "Programming Perls." If we store each number in 8 bytes we can store 250,000 numbers in one megabyte. Use a program that makes 40 passes over the input file. On the first pass it reads into memory any integer between 0 and 249,999, sorts the (at most) 250,000 integers and writes them to the output file. The second pass sorts the integers from 250,000 to 499,999 and so on to the 40th pass, which sorts 9,750,000 to 9,999,999.

如果输入流可以接收几次,这将是很大的 更简单(没有关于这方面的信息,想法和时间-性能问题)。

然后,我们可以数小数。如果是计数值的话 容易使输出流。通过计算值来压缩。它 这取决于输入流中的内容。

我有一台有1M内存的电脑,没有其他本地存储

另一种作弊方法:你可以使用非本地(网络)存储代替(你的问题不排除这一点),调用一个网络服务,它可以使用直接的基于磁盘的归并排序(或者只需要足够的RAM来在内存中排序,因为你只需要接受1M的数字),而不需要(公认非常巧妙的)已经给出的解决方案。

这可能是作弊,但不清楚你是在寻找一个现实问题的解决方案,还是一个让人扭曲规则的谜题……如果是后者,那么简单的欺骗可能比复杂但“真实”的解决方案(正如其他人指出的那样,后者只能用于可压缩输入)得到更好的结果。

如果数字的范围是有限的(只能有2个8位数,或者只有10个不同的8位数),那么你可以编写一个优化的排序算法。但如果你想对所有可能的8位数进行排序,这在内存那么少的情况下是不可能的。