有一项编程挑战需要根据序列起始编号和间隔长度生成 XOR 校验和。
它要求您根据间隔长度迭代序列,并且在每次迭代时都要减少为校验和计算选择的元素数量。
示例:的
如果起始编号 0 且间隔长度 3 ,则过程如下所示:
0 1 2 /
3 4 / 5
6 / 7 8
其中XOR(^)校验和为 0 ^ 1 ^ 2 ^ 3 ^ 4 ^ 6 == 2
同样,如果开头 17 且间隔长度 4 ,则流程如下:
17 18 19 20 /
21 22 23 / 24
25 26 / 27 28
29 / 30 31 32
产生校验和 17 ^ 18 ^ 19 ^ 20 ^ 21 ^ 22 ^ 23 ^ 25 ^ 26 ^ 29 == 14
我的解决方案
使用递归
import operator
import sys
sys.setrecursionlimit(20000)
def answer(start, length):
lst = [range(start+length*n, start+length*n+length) for n in xrange(length)]
return my_reduce(lst, length)
def my_reduce(lst, length):
if not lst: return 0
l = lst.pop(0)
return reduce(operator.xor, l[:length], 0) ^ my_reduce(lst, length-1)
使用生成器的迭代方法
def answer(start, length):
return reduce(operator.xor, gen_nums(start, length))
def gen_nums(start, length):
l = length
while l > 0:
for x in xrange(start, start+l):
yield x
start = start + length
l = l - 1
问题
我的两种方法运行速度不够快。
它们适用于琐碎的计算,例如示例中的那些,但是当间隔长度很大时需要更多的时间,例如 1000
我需要理解为什么我的解决方案表现不佳以及哪种算法和数据结构适合这一挑战。
答案 0 :(得分:6)
我建议对您的解决方案进行简单的优化。
使用此方法获取范围[a,b]
的xordef f(a):
res = [a, 1, a+1, 0]
return res[a%4]
def getXor(a, b):
return f(b) ^ f(a-1)
现在,对于给定的时间间隔,您可以在O(n)
而不是O(n^2)
中计算XOR校验和。
def gen_nums(start, length):
l = length
ans = 0
while l > 0:
ans^= getXor(start,start+l-1)
start = start + length
l = l - 1
return ans
<强>解释强>
让我们表示 f(n)=1⊕2⊕3⊕⋯⊕n,其中⊕表示XOR运算 那么 A 和 B 之间的所有数字的XOR可以用 f(B)⊕f(A-1)表示,因为 x⊕x= 0
现在我们可以轻松找到,
时间复杂度 - O(1)