Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/310.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/algorithm/12.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 快速访问成对运算的和_Python_Algorithm_Data Structures - Fatal编程技术网

Python 快速访问成对运算的和

Python 快速访问成对运算的和,python,algorithm,data-structures,Python,Algorithm,Data Structures,给定一个数字向量v,我可以通过使用累积和来访问该向量各部分的和,即,代替O(n) v=[1,2,3,4,5] 定义和v(i,j): 回报总额(v[i:j]) 我可以做O(1) 现在,我需要一个类似的东西,但是对于成对而不是求和: 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

给定一个数字向量
v
,我可以通过使用累积和来访问该向量各部分的和,即,代替
O(n)

v=[1,2,3,4,5]
定义和v(i,j):
回报总额(v[i:j])
我可以做
O(1)

现在,我需要一个类似的东西,但是对于
成对
而不是
求和

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。显然,可以两两预先计算
的所有值,因此解决方案在时间和空间上都应该是
o(n^2)
(最好是线性的)。

对于二进制操作,例如
或xor
,可以使用
o(n)
算法。
让我们考虑这个例子的XOR,但这可以很容易地修改为//和。 这里需要注意的最重要的一点是,两个数字的位
x
上的二进制运算符的结果不会影响位
y
的结果。(您可以通过尝试类似于
010^011=001
的方法很容易看出这一点。因此,我们首先计算所有数字中最左边的位对最终和的贡献,然后是下一个最低有效位,依此类推。下面是一个简单的算法/伪代码:

  • 构造一个简单的表
    dp
    ,其中
    dp[i][j]=范围[i,n]内的数字计数,并设置第j位

  • 在大多数情况下,对于整数,原则上位数,您总是可以在Θ(n²)空间中预计算每个可能的输出,然后回答Θ(1)中的查询通过在预计算表中查找它。其他一切都是一种权衡,取决于预计算时间、空间和实际计算时间的成本;有趣的问题是o(n²)可以做什么空间,即次二次。这通常取决于应用程序和二进制运算的属性
    f

    f
    *
    的特定情况下,我们可以仅使用Θ(n)空间进行Θ(1)查找:我们将利用
    p
    中的对的和等于所有对的和,减去
    p=q
    中的对之和,除以2来说明
    p>q
    中的对

    #输入数据
    v=[1,2,3,4,5]
    n=len(v)
    #预计算
    部分和=[0]*(n+1)
    部分和平方=[0]*(n+1)
    对于枚举(v)中的i,x:
    部分和[i+1]=部分和[i]+x
    部分和平方[i+1]=部分和平方[i]+x*x
    #查询响应
    def成对(i,j):
    s=部分和[j]-部分和[i]
    s2=部分和平方[j]-部分和平方[i]
    返回(s*s-s2)/2
    

    更一般地说,只要
    f
    是可交换的,并且分布在累加器操作上(在本例中为
    +
    ),该方法就可以工作。我在这里编写的示例没有使用itertools,因此它更容易翻译为其他语言,因为这个问题是与语言无关的。

    我认为你不能比O(N^2)做得更好在这里,因为有N^2个值需要考虑。可以进行的任何优化都与运算符的属性有关(例如:如果运算是XOR,则进行位操作等)@AbhinavMathur:谢谢,你会为XOR做什么?(
    f=^
    )numpy是一个选项吗?@PranavHosangadi:我在寻找一个算法,而不是它的实现;如果
    numpy
    实现了一些东西,我可以处理它。然而,问题是加速方面的
    O
    ,而不是在
    C
    中重写。numpy使用SIMD操作来获得它所实现的加速,这在香草中是不可能的因此,您的算法仍然是
    O(无论什么)
    ,但由于并行处理的数据更多,因此作业运行速度更快。
    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
    
    l = [5,3,1,7,8]
    n = len(l)
    ans = 0
    
    max_binary_length = max(log2(i) for i in l)+1  #maximum number of bits we need to check
    
    for j in range(max_binary_length):
        # we check the jth bits of all numbers here
        for i in range(0,n):
            # we need sum((l[i]^l[j]) for j in range (i+1,n))
            current = l[i]
            if jth bit of current == 0:
                # since 0^1 = 1, we need count of numbers with jth bit 1
                count = dp[i+1][j]
            else:
                # we need count of numbers with jth bit 0
                count = (n-i)-dp[i+1][j] 
                # the indexing could be slightly off, you can check that once
            ans += count * (2^j)
            # since we're checking the jth bit, it will have a value of 2^j when set
    print(ans)