给定一个数为v
的向量,我可以通过使用累积和来访问该向量的各部分的和,即,代替O(n)
v = [1,2,3,4,5]
def sum_v(i,j):
return sum(v[i:j])
我能做O(1)
import itertools
v = [1,2,3,4,5]
cache = [0]+list(itertools.accumulate(v))
def sum_v(i,j):
return cache[j] - cache[i]
现在,我需要类似的东西,但是对于pairwise
而不是sum_v
:
def pairwise(i,j):
ret = 0
for p in range(i,j):
for q in range(p+1,j):
ret += f(v(p),v(q))
return ret
其中f
是,优选地,相对地任意的事物(例如*
或^
或…)。然而,只为产品或XOR工作的东西也会很好
PS1。我希望在^{
PS2。问题在于算法,而不是实现,因此语言不可知。我之所以给它加上标签python
,只是因为我的示例是用python编写的
PS3。显然,可以预先计算pairwise
的所有值,因此解在时间和空间上都应该是o(n^2)
(最好是线性的)
原则上,您总是可以在Θ(n²)空间中预计算每个可能的输出,然后只需在预计算表中查找即可回答Θ(1)中的查询。其他一切都是一种权衡,取决于预计算时间、空间和实际计算时间的成本;有趣的问题是o(n²)空间可以做什么,即次二次空间。这通常取决于应用程序和二进制操作
f
的属性在
f
为*
的特殊情况下,我们可以仅使用^(n)空间进行^(1)查找:我们将利用p < q
的对的和等于所有对的和减去p = q
的对的和除以2来说明p > q
的对更一般地说,每当
f
是可交换的并且分布在累加器操作上时(在本例中为+
),这就可以工作。我在这里写了一个没有itertools的例子,因此它更容易翻译成其他语言,因为这个问题是不可知语言的对于诸如
or, and, xor
之类的二进制操作,可以使用O(N)
算法。让我们考虑这个例子的XOR,但这可以很容易地修改为//和。 这里需要注意的最重要的一点是,两个数字的位
x
上的二进制运算符的结果不会影响位y
的结果。(您可以通过尝试类似010 ^ 011 = 001
的方法很容易看出这一点。因此,我们首先计算所有数字中最左边的位对最终和的贡献,然后是下一个最低有效位,依此类推。下面是一个简单的算法/伪代码:dp
,其中dp[i][j] = count of numbers in range [i,n) with jth bit set
在大多数情况下,对于整数,位数<;=32。因此这应该具有
O(N*log2(max(A[i])))
=O(N*32)
=O(N)
的复杂性相关问题 更多 >
编程相关推荐