1442. 形成两个异或相等数组的三元组数目
题目描述
给你一个整数数组 arr 。
现需要从数组中取三个下标 i、j 和 k ,其中 (0 <= i < j <= k < arr.length) 。
a 和 b 定义如下:
a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]
b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k]
注意:^ 表示 按位异或 操作。
请返回能够令 a == b 成立的三元组 (i, j , k) 的数目。
示例 1:
输入:arr = [2,3,1,6,7]
输出:4
解释:满足题意的三元组分别是 (0,1,2), (0,2,2), (2,3,4) 以及 (2,4,4)
示例 2:
输入:arr = [1,1,1,1,1]
输出:10
示例 3:
输入:arr = [2,3]
输出:0
示例 4:
输入:arr = [1,3,5,7,9]
输出:3
示例 5:
输入:arr = [7,11,12,9,5,2,7,17,22]
输出:8
提示:
1 <= arr.length <= 300
1 <= arr[i] <= 10^8
解题思路
记住一点,本题考的是,异或的求解口诀:同为0,异为1
我们只要直到这点,就可以将暴力中的O(n ^ 3)优化成O(n ^ 2),只需要枚举左区间i和右区间k,由于只有相同的两个数异或之后才会为0,所以我们只要判断一个区间的异或结果是否为0即可,但是这里要注意,j>i,所以为什么累加的是(k - i),而不是(k - i + 1)
暴力代码(切记不要写,看看就好)
1 class Solution { 2 public int countTriplets(int[] arr) { 3 int n = arr.length; 4 int[] prefix = new int[n + 1]; 5 for (int i = 1; i <= n; i++) { 6 prefix[i] = prefix[i - 1] ^ arr[i - 1]; 7 } 8 int total = 0; 9 for (int i = 0; i < n; i++) { 10 for (int j = i + 1; j < n; j++) { 11 for (int k = j; k < n; k++) { 12 int a = prefix[j] ^ prefix[i]; 13 int b = prefix[k + 1] ^ prefix[j]; 14 if (a == b) { 15 total++; 16 } 17 } 18 } 19 } 20 21 return total; 22 } 23 }
提交反馈
优化代码
1 class Solution { 2 public int countTriplets(int[] arr) { 3 int len = arr.length; 4 int ans = 0; 5 6 for(int i = 0; i < len - 1; i ++){ 7 // 累计前缀异或的结果 8 int sum = 0; 9 for(int k = i; k < len ; k ++){ 10 sum ^= arr[k]; 11 // 两数相同时,异或结果为0(充要条件)<=== (异或口诀:同为0,异为1) 12 if (sum == 0 && k > i) { 13 ans += (k - i); 14 } 15 } 16 } 17 return ans; 18 } 19 }
提交反馈
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· 开发者必知的日志记录最佳实践
· SQL Server 2025 AI相关能力初探
· Linux系列:如何用 C#调用 C方法造成内存泄露
· AI与.NET技术实操系列(二):开始使用ML.NET
· 没有Manus邀请码?试试免邀请码的MGX或者开源的OpenManus吧
· 无需6万激活码!GitHub神秘组织3小时极速复刻Manus,手把手教你使用OpenManus搭建本
· C#/.NET/.NET Core优秀项目和框架2025年2月简报
· DeepSeek在M芯片Mac上本地化部署
· 葡萄城 AI 搜索升级:DeepSeek 加持,客户体验更智能