假设我有一个值向量,表示要对(bin)值进行分类的类的上限。例如,向量{1,3,5,10}代表区[0,1 [,[1,3],[3,5 [和[5,10]。如何在恒定时间内在这些类(0,1,2,3)之一中实现随机值V的分类?走过边界列表并且一旦V超过bin的上边界就停止;这是微不足道的。但那个O(n)的箱数是多少;我希望能在不变的时间内做到这一点。
在我实际输入代码之前,我认为这是微不足道的,通过设置查找表,根据类边界将每个V除以某个值,然后使用除法的(舍入)结果来查找bin查找表中的数字。但是我发现它比我想象的要难得多,无论bin边界之间的比例距离如何,它都能以最小化查找表的大小同时最小化查找表的大小。并以一种适用于所有真实价值观的方式。使用谷歌我只找到决定垃圾箱边界的算法,至少使用我所做的术语。
答案 0 :(得分:1)
我怀疑在没有利用给定数字的某些属性的情况下,有一种方法可以在严格恒定的时间(并且不需要无限空间)中执行此操作。
查找表是一个不错的主意,但浮点值使这很困难。如果位数是有限的,您可以考虑将查找表表示为基本上trie (每个级别代表一个数字的树)。
因此对于{1, 2.5, 5, 9}
,您的树看起来像这样:
root
/ / / / | \ \ \ \ \
0 1 2 3 4 5 6 7 8 9
/ | \
2.0 ... 2.5 ... 2.9
每个叶子节点都包含一个值,表明它属于哪个区间,所以
0将被设置为0,
1,2.0 - 2.4全部设为1,
2.5 - 2.9,3 - 4将设为2,
5 - 9将设置为3
查询只涉及从根开始并反复进入与我们正在查找的数字中的下一个数字相对应的子节点(如果你在上面的树中查找2.65,你首先转到2,然后2.6,那么,因为它是一片叶子,你停下来并返回它的值,即1)。
查询的时间复杂度为O(d)
,其中d
是向量中有效数字的位数,空间复杂度为O(nd)
。
这可能听起来不是特别有效,但请注意d
是位数的数量 - 例如d = log m
m
如果我们谈论正整数,那么它就是最大可能值。
O(log n)
就相当简单了。
查找看起来与您搜索BST的方式非常相似 - 从根开始向左或向右移动直到找到值,除非在这种情况下您注意到您访问的每个节点并返回映射的索引最接近的值并不大。有些API的方法基本上适用于您(例如C ++中的std::map
)。
答案 1 :(得分:0)
我认为获得O(1)的唯一方法是创建一个查找表,以便您可以直接查找所有值。
如果边界表现良好,这只是可行的:
预期数字是整数,或边界是整数或精度有限。这允许您在检查查找表之前向下舍入(下)数字,并大大减少表格所需的条目。
最大和最小边界之间的差异不能太大。让我们说我们知道边界的精度是0.5,min是1,最大值是10,那么查找表需要(10-1)/0.5 = 18个条目。
对第一组和最后一组(小于最小值和大于最大值)的检查是通过简单的检查完成的,如果检查不会影响复杂性。