我需要按价格实施产品的分面搜索,即我希望有效地生成一系列范围,其中包含每个范围内的产品数量。
出于各种原因,我可以建立的最好的东西是一个表格,每个产品都给出了产品的最小和最大可能价格,例如:
idProduct | priceMin | priceMax 1 | 15 | 20 2 | 2 | 3 3 | 5 | 7 4 | 13 | 19
我们可以假设所有数字都是自然整数。
为了提高查询效率,我希望找到一个s
大小,以确保每个产品都有一个自然数k,例如:
k * s <= priceMin && priceMax <= (k + 1) * s
换句话说,预先计算范围列表,以便很容易确定给定产品是否属于其中一个范围。
使用上面的数据,数字12是s
的合适值,因为:
1 * 12 <= 15 && 20 <= 2 * 12
0 * 12 <= 2 && 3 <= 1 * 12
0 * 12 <= 5 && 7 <= 1 * 12
1 * 12 <= 13 && 19 <= 2 * 12
但是,数字6不是s
的合适值,因为它不适用于产品#3 0 * 6 <= 5
但7 > 1 * 6
在现实世界中,价格表将有数十万行,因此我正在寻找一种有效的算法,可以让我找到s
的最小可能值。
如果这是一个经典问题并且您知道它的名字,我可以从那里谷歌,但到目前为止我还无法找到任何相关内容。
答案 0 :(得分:1)
这是一个相当有效的算法(O(n + P log P),其中P是最大价格,假设整数价格)。 (我担心你的约束对你的喜好来说太大了,但是呃。)
观察(如Jan Dvorak先做的那样)条件
there exists k such that k * s <= priceMin and priceMax <= (k + 1) * s
相当于
for all k, it holds that k * s <= priceMin or priceMax <= k * s
相当于
for all k, it does not hold that priceMin < k * s < priceMax.
证据不错,但我不打算把它写出来。
该算法的第一步是计算开放价格区间(priceMin, priceMax)
作为位图的并集。
deltaIntervalCount = [0] * (P + 1)
for priceMin, priceMax in priceIntervals:
deltaIntervalCount[priceMin + 1] += 1
deltaIntervalCount[priceMax] -= 1
intervalCount = [0] * (P + 1)
for p in range(1, P + 1):
intervalCount[p] = intervalCount[p - 1] + deltaIntervalCount[p]
forbidden = [intervalCount[p] > 0 for p in range(P + 1)]
该算法的第二步是按顺序尝试s的候选者。
for s in range(1, P + 1):
if all(not forbidden[k * s] for k in range(P // s + 1)):
return s