我有一个带有排序数字的表格,例如:
1 320102
2 5200100
3 92010023
4 112010202
5 332020201
6 332020411
:
5000000000 3833240522044511
5000000001 3833240522089999
5000000002 4000000000213312
给定记录号,我需要 O(log n) 时间内的值。记录号为 64 位长,没有丢失的记录号。这些值是 64 位长的,它们已排序并且 value(n) < value(n+1)。
显而易见的解决方案是简单地做一个数组并使用记录号作为索引。这将花费 64 位每个值。
但我想要一种更节省空间的方式来做到这一点。因为我们知道值总是在增加,这应该是可行的,但我不记得让我这样做的数据结构。
一个解决方案是在数组上使用 deflate,但这不会给我 O(log n) 来访问一个元素 - 因此是不可接受的。
你知道一个可以给我的数据结构:
- O(log n) 用于访问
- 空间要求 < 64 位/值
= 编辑 =
由于我们事先知道所有数字,因此我们可以找到每个数字之间的差异。通过取这些差异的第 99 个百分位,我们将得到一个相对适中的数字。取 log2 将为我们提供表示适度数字所需的位数 - 让我们称之为适度位数。
然后创建这个:
64-bit value of record 0
64-bit value of record 1024
64-bit value of record 2048
64-bit value of record 3072
64-bit value of record 4096
然后是所有记录的增量表:
modest-bits difference to record 0
modest-bits difference to previous record
1022 * modest-bits difference to previous record
modest-bits difference to record 1024
记录 k*1024 的适度位差异将始终为 0,因此我们可以将其用于信令。如果它不为零,那么接下来的 64 位将是一个指向简单数组的指针,用于将接下来的 1024 条记录作为 64 位值。
由于选择适度的值作为第 99 个百分位数,因此最多会发生 1% 的时间,因此最多浪费 1% * n * 适度位 + 1% * n * 64 位 * 1024。
空间:O(适度位 * n + 64 位 * n / 1024 + 1% * n * 适度位 + 1% * n * 64 位 * 1024)
查找:O(1 + 1024)
(99% 和 1024 可能需要调整)
= 编辑2 =
基于上面的想法,但浪费的空间更少。创建这个:
64-bit value of record 0
64-bit value of record 1024
64-bit value of record 2048
64-bit value of record 3072
64-bit value of record 4096
对于所有不能用适度位表示的值,将大值表创建为树:
64-bit position, 64-bit value
64-bit position, 64-bit value
64-bit position, 64-bit value
然后是所有记录的增量表,每 1024 条记录重置:
modest-bits difference to record 0
modest-bits difference to previous record
1022 * modest-bits difference to previous record
modest-bits difference to record 1024
但也会为大值表中的每个值重置。
空间:O(modest-bits * n + 64-bit * n / 1024 + 1% * n * 2 * 64-bit)。
查找需要搜索大值表,然后查找第 1024 个值,最后将适度位值相加。
查找:O(log(大值表) + 1 + 1024) = O(log n)
你能改善这个吗?或者以不同的方式做得更好?