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 }
提交反馈