《编程珠玑》第一章第九题

来源:互联网 发布:php免费空间有哪些 编辑:程序博客网 时间:2024/05/22 15:29

原题:

使用更多的时间来换取更少的运行时间存在一个问题:初试化空间本身需要消耗大量的时间。说明如何设计一种技术,在第一次访问向量的项时将其初始化为0,。你的方案应该尽可能的使用常量的时间进行初始化和向量访问,使用的额外空间应正比于向量的大小。因为该方法通过进一步增加空间来减少初始化时间,所以仅在空间很廉价、时间很宝贵且向量很稀疏的情况下才考虑使用。


书后的参考答案:

借助于两个额外的n元向量from、to和一个整数top,我们就可以使用标示来初始化向量data[0...n-1]。如果元素data[i]已经初始化,那么from[i]<top并且to[from[i]]=i。因此,from是一个简单的标示,to和top一起确保了from中不会被写入内存里的随机内容,下图中的data的空白项未被初始化:



变量top初试化为0,下面的代码实现对数组元素i的首次访问:

from[i] = top

to[top] = i

data[i] = x

top++


在上图中,数据的访问顺序为:3 2 8。初试时三个数组都没有进行初始化,不然就违背了节约时间的目的。

最初试的想法就是使用一个等长度的boolean数组来标示原数组的元素是否被访问过,但是这样就必须初始化boolean数组,违背的最初目的。

因为数组都没初始化的过程,所以不能使用简单的01标记来标示对应的元素是不是被访问过,所以在标记数组(from)中记录是第几个(top)被访问,但是这样仍然不够,随着top的变大,from数组中会有越来越多的未被初始化的元素的值小于top,从而使得from[i]<top为真,导致错误。

to数组的出现就是为了解决上个问题,top和to一起保证from中的标记是正确的。

下面证明如果访问一个未被初试的元素(假设为j),那么from[j]<top并且to[from[j]]=j一定为假。

因为访问一个之前没有初试化的元素,那么j一定不等于之前的所有i,比如上图,1 3 5已经访问过了,那么j一定不是1 3 5。采用反证法,假设from[j]<top并且to[from[j]]=j为真。

from[j] < top为真,这必然有to[form[j]]为之前出现过的某一个i,又有”j一定不等于之前的所有i“,那么to[from[j]]=j为假,矛盾,所以from[j]<top并且to[from[j]]=j一定为假。

所以,如果data[i]已经初始化,必然有from[i]<top并且to[from[i]]=i(根据定义可知)。上述就证明了如果from[i]<top并且to[from[i]]=i,data[i]必然已经被初始化。


原创粉丝点击