如何找到所有异或0的子数组?
How to find all the subarrays with xor 0?
问题是找到给定数组的所有子数组,其所有元素的异或都等于零。
例如,如果数组包含元素 [13,8,5,3,3]
,解决方案应给出所有子数组的索引,如 0-2
、3-4
、0-4
等。
问题与
中的问题相似
唯一的区别是我想要满足方程A0 xor A1 xor...xor An = 0
的所有子数组的索引
如果你有两个不同的数组前缀,它们的异或相等,假设长度为 x1 的前缀和长度为 x2 的前缀,那么从 x1 + 1 到 x2 的子数组的 xor 等于 0。制作字典 (BST, hash table,任何类似的)并在那里存储对(前缀和的值,给出该值的前缀)。任何两个具有相同值的元素都会给你一个子数组。如果你愿意,你也可以使用 Trie 查找它。
使用特里树:
一开始Trie由单节点组成,没有边。我们想给它加上数字。索引它们也很方便,因为我们想找到所有子数组。 Trie 中表示一些数字(如果重复则为多个)的每个节点将存储其索引列表,因此我们可以轻松获取子数组。
当我们将一个数字 n 与索引 i 相加时,我们将 n 写为二进制数。我们从初始节点开始。如果 n 的最高有效位等于 0,如果从一开始就存在标记为 0 的边,那么我们移动到相应的顶点,如果不存在,我们创建一个标记为 0 的新边指向一个新节点,然后我们移动到这个新创建的一个(1 同样的事情)。然后我们继续这样做,直到我们遍历 n 的每一位。我们将索引 i 添加到我们最终所在的节点中的索引列表中。
- 使变量 prefsum = 0
- 对于每个 i = 1 到 n:
- 将 prefsum 添加到索引为 i 的 Trie
- 设置prefsum = prefsum ^ array[i]
- 检查Trie中是否存在value prefsum。对于每个这样的值 v,xor 等于 0 的子数组在索引 v-th 和 i-th 之间。
总复杂度为 O(n * log(数组中的最大值))
它可能并不比使用 BST 或哈希数组更好,但它是一种流行的技巧,尤其在一些 XOR 运算的问题中表现出色。
这是对链接问题的一个相当直接的扩展。在 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]
的异或等于 array[:j]
的异或时,子数组 array[i:j]
的异或为零。对于数组的每个后续元素,我们计算以该元素结尾的前缀与以前一个元素结尾的前缀的异或,然后查找上述等式的所有解 i
。然后我们插入新的关联并继续。
如果您想修改 post 中提到的答案,那么我希望您已经很好地理解了该解决方案。
现在该解决方案中缺少的是它仅存储特定前缀 xor 和的第一个索引出现。不跟踪出现相同 xorSum 的其他索引。因此,您要做的是修改 map 以保留每个 xorSum 的索引列表(C++ 中的向量)。
我会在Python3.7
写代码块
令 l 为 (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]是一个异或为零的子数组:
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)).
问题是找到给定数组的所有子数组,其所有元素的异或都等于零。
例如,如果数组包含元素 [13,8,5,3,3]
,解决方案应给出所有子数组的索引,如 0-2
、3-4
、0-4
等。
问题与
唯一的区别是我想要满足方程A0 xor A1 xor...xor An = 0
如果你有两个不同的数组前缀,它们的异或相等,假设长度为 x1 的前缀和长度为 x2 的前缀,那么从 x1 + 1 到 x2 的子数组的 xor 等于 0。制作字典 (BST, hash table,任何类似的)并在那里存储对(前缀和的值,给出该值的前缀)。任何两个具有相同值的元素都会给你一个子数组。如果你愿意,你也可以使用 Trie 查找它。
使用特里树:
一开始Trie由单节点组成,没有边。我们想给它加上数字。索引它们也很方便,因为我们想找到所有子数组。 Trie 中表示一些数字(如果重复则为多个)的每个节点将存储其索引列表,因此我们可以轻松获取子数组。
当我们将一个数字 n 与索引 i 相加时,我们将 n 写为二进制数。我们从初始节点开始。如果 n 的最高有效位等于 0,如果从一开始就存在标记为 0 的边,那么我们移动到相应的顶点,如果不存在,我们创建一个标记为 0 的新边指向一个新节点,然后我们移动到这个新创建的一个(1 同样的事情)。然后我们继续这样做,直到我们遍历 n 的每一位。我们将索引 i 添加到我们最终所在的节点中的索引列表中。
- 使变量 prefsum = 0
- 对于每个 i = 1 到 n:
- 将 prefsum 添加到索引为 i 的 Trie
- 设置prefsum = prefsum ^ array[i]
- 检查Trie中是否存在value prefsum。对于每个这样的值 v,xor 等于 0 的子数组在索引 v-th 和 i-th 之间。
总复杂度为 O(n * log(数组中的最大值))
它可能并不比使用 BST 或哈希数组更好,但它是一种流行的技巧,尤其在一些 XOR 运算的问题中表现出色。
这是对链接问题的一个相当直接的扩展。在 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]
的异或等于 array[:j]
的异或时,子数组 array[i:j]
的异或为零。对于数组的每个后续元素,我们计算以该元素结尾的前缀与以前一个元素结尾的前缀的异或,然后查找上述等式的所有解 i
。然后我们插入新的关联并继续。
如果您想修改 post 中提到的答案,那么我希望您已经很好地理解了该解决方案。 现在该解决方案中缺少的是它仅存储特定前缀 xor 和的第一个索引出现。不跟踪出现相同 xorSum 的其他索引。因此,您要做的是修改 map 以保留每个 xorSum 的索引列表(C++ 中的向量)。
我会在Python3.7
写代码块令 l 为 (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]是一个异或为零的子数组:
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)).