求存在异或和为0子序列的最短子数组算法求助
问题解法思路
核心观察:鸽巢原理的应用
异或运算的本质是GF(2)域上的线性运算,每个整数可看作30位二进制向量(因1e9 < 2^30)。根据线性代数基本结论:30维空间中任意31个向量必然线性相关,即存在非空子序列异或和为0。因此满足条件的最短子数组长度一定不超过31,无需考虑更长的区间。
具体算法步骤
- 特殊情况处理:若数组中存在元素0,直接返回1(单个0的子数组即满足要求)。
- 暴力枚举短区间:遍历每个位置作为子数组右端点,向左最多检查30个元素(确保子数组长度≤31),用线性基判断该区间是否存在异或和为0的子序列:
- 对每个右端点
i,初始化空线性基(长度30的数组,初始值为0)。 - 从
i向左遍历j(范围max(0, i-30)到i):- 将
A[j]插入线性基:- 从最高位(29位)到最低位(0位)遍历:
- 若当前位为1且线性基对应位置为空,则将
A[j]存入该位置,终止插入。 - 若当前位为1且线性基对应位置不为空,则将
A[j]异或该位置的基向量,继续处理下一位。
- 若当前位为1且线性基对应位置为空,则将
- 若插入后
A[j]变为0,说明A[j]可被当前线性基表示,即[j, i]区间存在异或和为0的子序列。此时记录区间长度i-j+1,更新全局最短长度,然后终止内层循环(更左边的区间长度更大,无需继续)。
- 从最高位(29位)到最低位(0位)遍历:
- 将
- 对每个右端点
- 返回结果:遍历结束后,得到的最短长度即为答案(因数组长度≥31时必然存在长度≤31的解,故答案一定存在)。
时间复杂度分析
- 外层遍历:O(n),n为数组长度。
- 内层遍历每个右端点最多30个元素,每个元素插入线性基需30次位运算:O(30*30)。
- 总复杂度:O(n3030) = 9e6 次运算,完全满足n≤1e5的约束。
线性基的作用
线性基是模2高斯消元的简化实现,用于维护一组向量的极大线性无关组。若插入元素时被异或为0,说明该元素与已存入的基向量线性相关,即存在非空子序列的异或和为0,这正是我们需要的判断条件。
内容的提问来源于stack exchange,提问作者astro
相关产品推荐
相关产品推荐

