如何找到所有xor为0的子数组?

时间:2019-08-05 20:10:44

标签: arrays algorithm bit-manipulation xor bitwise-xor

问题是找到给定数组的所有子数组,并将其所有元素的xor等于零。

例如,如果数组包含元素[13,8,5,3,3],则解决方案应提供所有0-23-40-4等子数组的索引。

问题类似于被问到的here

唯一的区别是我希望所有满足方程A0 xor A1 xor...xor An = 0的子数组的索引

4 个答案:

答案 0 :(得分:2)

这是链接问题的相当简单的扩展。在Python中,

# Multivalued map from the XOR of array[:i] to i for all i.
prefix_xor_to_stops = {0: [0]}
prefix_xor = 0
for j, x in range(array):
    prefix_xor ^= x
    # Returns the value associated with prefix_xor. Inserts [] if not present.
    stops = prefix_xor_to_stops.setdefault(prefix_xor, [])
    for i in stops:
        yield (i, j+1)
    stops.append(j+1)

和以前一样,想法是子数组array[i:j]的XOR为零,且仅当array[:i]的XOR等于array[:j]的XOR时。对于数组的每个后续元素,我们从在上一个元素结束的前缀的XOR计算在该元素结束的前缀的XOR,然后查找上述方程式的所有解i。然后,我们插入新的关联并继续。

答案 1 :(得分:2)

如果您想修改帖子中提到的答案,那么我希望您对这个解决方案非常了解。 现在,该解决方案缺少的是它仅存储特定前缀xor和的第一个索引出现。不会跟踪发生相同xorSum的其他索引。因此,您需要做的是修改映射以为每个xorSum保留一个索引列表(C ++中的向量)。

答案 2 :(得分:1)

如果数组的两个不同前缀的xor相等,则假设长度为x1的前缀和长度为x2的前缀,则从x1 +1到x2的子数组的xor等于0。创建一个字典(BST,哈希表) ,类似的东西)并在那里存储对(前缀和值,即给出该值的前缀)。具有相同值的任何两个元素将为您提供一个子数组。您也可以根据需要使用Trie查找它。

使用Trie:

在开始时,Trie由单个节点组成,没有边缘。我们要添加数字。为它们建立索引也很方便,因为我们要查找所有子数组。在Trie中代表某些数字(在重复的情况下为多个)的每个节点将存储其索引列表,因此我们可以轻松获得子数组。

当我们将数字n与索引i相加时,我们将n写为二进制数。我们从初始节点开始。如果n的最高有效位等于0,如果从开始就存在标记为0的边,那么我们将移至相应的顶点;如果不存在,则创建指向0的新边指向新节点,然后将其移至新创建的边。一个(与1相同)。然后我们继续这样做,直到遍历n的每一位为止。我们将索引i添加到最终到达的节点中的索引列表中。

  1. 使变量prefsum = 0
  2. 对于每个i = 1至n:
    • 使用索引i向特里添加prefsum
    • 设置prefsum = prefsum ^ array [i]
    • 检查Trie中是否存在值首选项。对于每个这样的值v,xor等于0的子数组位于索引v-th和i-th之间。

总复杂度为O(n * log(数组中的最大值))

它可能不会比使用BST或哈希数组更好,但它是一个流行的技巧,尤其在XOR操作的某些问题上很有用。

答案 3 :(得分:1)

我将在Python 3.7中编写代码块

让我成为(i,j)的元组列表

处理问题的最有效,最简单的方法是:

步骤1:计算前缀的异或:

xorArr[0] = arr[0] #here arr = [13,8,5,3,3]
for i in range(1, n): 
    xorArr[i] = xorArr[i - 1] ^ arr[i]

第2步:检查xorArr [i] = 0是否在任意点,如果是,则arr [:i + 1]是一个xor为零的子数组:

for i in range(1, n): 
    xorArr[i] = xorArr[i - 1] ^ arr[i] 
    if xorArr[i]==0:
        l.append((0,i))

第3步:现在制作一个字典来存储xorArr中出现的每个元素的索引列表

d = {xorArr[0]:[0]}
for x in range(1,n):
    if xorArr[x] in d.keys():
        d[xorArr[x]].append(x)
    else:
        d[xorArr[x]] = [x]

第4步:创建一个函数,将d [xorArr [x]]中的每个元素配对(i,j)并将其添加到l:

from itertools import combinations
def pair_up(arr):
    return list(combinations(arr,2))
for x in d.values():
    if len(x)==1: #you don't have to worry about elements that occur only once
        continue 
    else:         # if same element is present at i and j (i<j) then
        l+=pair_up(x) # all pairs of (i,j) are valid (xor(arr[i:j]) = 0)

P.S:您不必担心排序,因为d中的所有值显然都会被排序。希望这可以帮助。 做投票。干杯!

编辑:

代码的复杂度:O(n *((xorArr中具有最大频率的元素的频率选择2))或O(n *(max_freq C 2))。