我们能否在O(n)时间内找到整数数组的所有子数组的按位异或?

时间:2017-02-24 18:39:46

标签: algorithm

如何找到数组A的所有子数组的值的按位异或

A = [1,2]
Output : 0

Explanation : 
Sub Arrays :`[1], [2], [1,2]` (XOR of all subarrays = 0)

2 个答案:

答案 0 :(得分:1)

要回答这个问题,必须为每个元素决定它是出现在奇数还是偶数个子数组中。奇怪的是,它会出现在xor总和中,即使它不会出现。

位置i的元素将包含在(i+1) * (n-i)子阵列中。这是因为任何包含i的子数组都从索引0,1,...,i开始。并在索引i,i + 1,...,n-1结束。现在(i+1) * (n-1) = i(n-1) + i*i + n = (i+1)n (mod 2) x^2 = x (mod 2),因为任何x都是n

因此,如果n是偶数,则奇数个子数组中不会出现任何元素。如果def xor_all_subarrays(A): if len(A) % 2 == 0: return 0 r = 0 for i in xrange(0, len(A), 2): r ^= A[i] return r 为奇数,偶数索引处的元素将出现在奇数个子数组中。

所以:

export function serverLog(input) {
    http.post('server-log', input);
}

答案 1 :(得分:1)

如果使用子阵列表示 powersets ,则可以使用以下事实:

  • 对于大小 n 的列表,有2个 n 列表,每个元素出现在 2 n / 2 ;和
  • 按位xor操作是可交换的和关联的:x ^ y ^ z等于z ^ x ^ y

现在,如果列表大于一个元素,则每个元素都会出现: 2 n / 2 次,这是 2的幂。如果您对元素进行两次xor,则每个0的结果为x ^ x = 0x。因此,由于它是2的幂(大于或等于2),每个元素的xoring为2的幂,结果将为0。如果有一个元素,则两个子数组为[][x],因此在这种情况下,结果为x。所以快速算法是:

def xor_subarrays_powerset(data):
    if len(data) == 1:
        return data[0]
    else:
        return 0

如果这些是基于索引的连续列表,则故事有点不同:

  • 此处元素 j (零索引)将位于:

     n
    ---  
    \     
    /    min(j+1,n,i-n+1,n-j)
    ---  
    i=1
    

确实如果您有一个列表[1,2,3,4]:有以下“窗口”:

1,2,3,4
x
  x
    x
      x
1 1 1 1
x x
  x x
    x x
1 2 2 1
x x x
  x x x
1 2 2 1
x x x x
1 1 1 1
-------
4 6 6 4

以及长度为5的列表

1,2,3,4,5
x
  x
    x
      x
        x
1 1 1 1 1
x x
  x x
    x x
      x x
1 2 2 2 1
x x x
  x x x
    x x x
1 2 3 2 1
x x x x
  x x x x
1 2 2 2 1
x x x x x
1 1 1 1 1
---------
5 8 9 8 5

那么我们注意到了什么:

  • 对于列表,第一个和最后一个元素始终计为 n 次。这是合乎逻辑的,因为每个移动窗口只通过这些元素一次。
  • 第二个和一个但最后一个元素总是计算 2×(n-2)+2 次。由于所有窗户除了最小和最大通过两次;
  • 第三个和第二个但最后一个元素总是计算 3×(n-4)+ 2×2 + 2 次;
  • 第四个和三个但最后一个元素总是计算 4×(n-6)+ 3×2 + 2×2 + 2 ;一般来说:
  • i -th和 ni -th元素(索引为零,i≤n/ 2 )计算(i 1)×(N-2×I)+ ... ... 并不重要,因为它们是所有两个的倍数。由于与自身相关的元素为0,因此两个的倍数不计算在内。

所以现在我们只需要确定元素对总数的贡献是偶数还是奇数。我们知道如果列表的长度是偶数, n 是偶数,因此所有(n-2×i),这意味着没有元素将贡献,结果因此0。如果列表是奇数,第一个元素将贡献奇数(因为(i + 1)×(n-2×i)是奇数)并且下一个元素将贡献均匀,下一个元素将再次贡献奇数。

因此,如果列表具有奇数长度,则意味着我们只需要对位于024的元素进行xor,...我们可以这样做用:

from itertools import islice

def xor_subarrays_contiguousness(data):
    if len(data)&1:
        r = 0
        for e in islice(data,0,None,2):
            r ^= e
        return r
    else:
        return 0