时间与空间的交换
复习
- 算法与正确性:算法既要正确,又要考虑运行时间
- 大 O 记号:大 O 可以描述时间随规模的增长
- 数据结构:组织数据需要额外的时间和空间
TL;DR
- 用更多的空间,常常能换来更少的时间
- 查表、索引、缓存都是“空间换时间”的思路
- 也有反过来“时间换空间”的做法,比如压缩
- 关键不是哪个更好,而是场景需要哪种权衡
正文
衡量一个算法,通常要看两样东西:花的时间,和占的空间。有意思的是,这两样常常可以互相交换。
我们前面其实已经见过这个套路了。缓存,就是用一块更快的空间,去减少“跑到慢存储里取数”的时间;哈希表,则是用额外的一张表,去换取几乎一步到位的查找。它们都在做同一件事:用空间,买时间。
用空间买时间
最直白的例子,是查表。
假设程序需要频繁计算一个函数在整数 0 到 1000 上的取值。与其每次现算,不如提前把所有结果算好、存成一张表;之后用到时直接查,一步到位。
- 不查表:每次都要重新计算,时间是计算成本
- 查表:多占一张表的内存,但取值接近
O(1)
这就是典型的空间换时间:用一块额外的存储,把重复的计算省掉。
类似的思路到处都是:给数据库建索引、给函数结果加缓存、给常用数据做预处理。本质上,都是在说:多记一点,就能少算一点。
用时间换空间
反过来,也有用时间换空间的时候。压缩就是个好例子:把数据压得更小,能省下宝贵的存储和带宽,代价是每次使用都要先解压,多花一点时间。
在一些资源受限的场合——比如嵌入式设备内存有限、或者网络带宽紧张——人们宁愿多花点时间算,也不愿多占空间。这时,时间就成了一种可以花的“货币”。
没有白吃的午餐
要记住,这两种交换都不是白来的。多占的空间会挤占别的用途,多花的时间会影响响应速度。所以,选择哪种权衡,永远取决于你的场景:
- 内存充裕、追求速度?那就多用空间换时间
- 空间紧张、能忍受慢一点?那就反过来
数据结构与算法的很多设计,说到底,就是在这两种资源之间找一个最舒服的平衡点。
接下来介绍一个更精细的工具,它看待“偶尔很贵”的操作,视角和前面不太一样。
思考题 1
为什么说哈希表是“用空间换时间”?它换来了什么?
思考题 2
举一个你身边“用时间换空间”的例子,并说说这样做的理由。
小结
知识点
- 时间与空间常常可以互相交换
- 查表、索引、缓存是空间换时间
- 压缩等是时间换空间
- 权衡取决于具体场景的资源约束
参考资料
- Wikipedia(zh):时空权衡:用时间或空间互相换取
- Wikipedia(zh):查找表:预先保存结果以避免重复计算
思考题答案(仅供参考)
思考题 1
哈希表需要额外维护一张散列表(以及处理冲突的空间),占用的空间比简单地把元素排成一列要多。换来的,是查找时能根据键直接算出位置,接近一步到位,省去了逐个比较的时间。
思考题 2
比如压缩文件:保存时把它压小,省下磁盘空间;使用时先解压,多花一点时间。理由通常是存储或带宽资源紧张,而解压所需的时间可以接受。类似的还有图片的有损压缩、实时传输中的降质编码等。
协议
本作品采用知识共享署名-非商业性使用-相同方式共享 4.0 国际许可协议进行许可。
封面图
设计师 | 南国微雪