SWE · Coding

重叠区间XOR为零的三元组:公共端点被抵消两次

明确F(x,y)含两端,x≤y≤z,输出所有满足三元组。

题目重点:明确F(x,y)含两端,x≤y≤z,输出所有满足三元组。

题意与假设

这道练习题保留了面经中值得训练的核心约束,并将需要澄清的条件单独列出。现场拿到变体时,先和面试官确认这些条件。

  • 训练F(l,r)=XOR a[l..r],要求F(x,y) XOR F(y,z)=0,0≤x≤y≤z<n。
  • 严格x<y<z、返回count还是全部列表在正式题中待核;本文用非严格全输出合同。

解题路线

  1. 前缀P[t]是前t项XOR,Fxy=Px XOR P_(y+1),Fyz=Py XOR P_(z+1)。中间ay在两区间重复,化简为Px XOR P_(z+1) XOR ay=0。
  2. 固定y,把所有x≤y的Px按值存索引列表;枚举z≥y,查询Px=P_(z+1) XOR ay,逐个输出对应x。
  3. 不要误化成F(x,z)=0,因为公共ay出现两次抵消,与整个x..z只出现一次不同。全部零数组有Θ(n³)答案,任何完整输出算法不能保证O(n²)总时间。

手动走一遍

a=[1,1,1],(0,1,2)两段XOR都0,因此满足,但整个0..2 XOR1,不是0。单点x=y=z时Fxy=Fyz=ay,二者XOR恒0,因此每位置至少一个训练合同答案。

Python 参考实现

下面的代码按上文假设实现,适合本地运行并追加自己的测试用例。

代码区可横向滚动;使用键盘时,先聚焦代码区再按方向键查看。

def zero_triples(a):
    prefix=[0]
    for x in a:prefix.append(prefix[-1]^x)
    starts={};result=[]
    for y,value in enumerate(a):
        starts.setdefault(prefix[y],[]).append(y)
        for z in range(y,len(a)):
            target=prefix[z+1]^value
            for x in starts.get(target,()):result.append((x,y,z))
    return result

复杂度

O(n²+T)期望时间、O(n+T)空间含输出,T合法三元组数。仅count可存Px频数而不存索引列表,时间O(n²)空间O(n)。

易错点与追问

容易失分的边界

  • 重叠端点的inclusive定义不可省略。
  • 先把所有Px存表会输出x>y,违背顺序。

继续深挖

  • 严格x<y<z时插入x表和z循环应如何移动?
  • 若只返回count,怎样在所有零输入下避开巨大结果存储?
✓已复制微信号!