一、Problem
Given an array of integers arr. We want to select three indices i, j and k where (0 <= i < j <= k < arr.length).
Let’s define a and b as follows:
a = arr[i] ^ arr[i + 1] ^ ... ^ arr[j - 1]
b = arr[j] ^ arr[j + 1] ^ ... ^ arr[k]
Note that ^ denotes the bitwise-xor operation.
Return the number of triplets (i, j and k) Where a == b.
Input: arr = [2,3,1,6,7]
Output: 4
Explanation: The triplets are (0,1,2), (0,2,2), (2,3,4) and (2,4,4)
二、Solution
方法一:暴力(超時)
class Solution {
public int countTriplets(int[] arr) {
int cnt = 0, N = arr.length;
for (int i = 0; i < N-1; i++)
for (int j = i+1; j < N; j++) {
for (int k = j; k < N; k++) {
int a = arr[i];
for (int l = i+1; l <= j-1; l++)
a ^= arr[l];
int b = arr[j];
for (int l = j+1; l <= k; l++)
b ^= arr[l];
if (a == b) cnt++;
}
}
return cnt;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
方法二:優化
- 其實不用顯式地將 a 異或上區間 中的數,b 也不用,取而代之的是
- 第一層循環先確定 ,第二層循環先確定 ,第三層循環開始將區間 的數異或上 。
- 第三層循環結束,代表從 b 已經枚舉完畢,那麼 a 就可以繼續異或上第二層循環中的數。
這樣可將複雜度降爲 ,運算量大約爲 = 兩千七百萬,勉強過啦…
class Solution {
public int countTriplets(int[] arr) {
int cnt = 0, N = arr.length;
for (int i = 0; i < N-1; i++) {
int a = arr[i];
for (int j = i+1; j < N; j++) {
int b = arr[j];
for (int k = j; k < N; k++) {
if (k != j) b ^= arr[k];
if (a == b) cnt++;
}
a ^= arr[j];
}
}
return cnt;
}
}
前綴和
較容易理解的算法,預處理好每一段的異或和,
class Solution {
public int countTriplets(int[] arr) {
int cnt = 0, N = arr.length, pre[] = new int[N+1];
for (int i = 1; i <= N; i++) pre[i] = pre[i-1] ^ arr[i-1];
for (int i = 1; i <= N-1; i++)
for (int j = i+1; j <= N; j++)
for (int k = j; k <= N; k++) {
if ((pre[i-1] ^ pre[j-1]) == (pre[j-1] ^ pre[k]))
cnt++;
}
return cnt;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
不知道還有沒有更優的解法…
方法三:最優解
- 由位運算規則得:a^b=0,得
- 如果 a = b,即 arr[i] ^ … ^ arr[k] = 0,那麼 j 只要在 [i+1, k] 中選一個數即可,爲什麼?
- 由上可得,如果 a[i] ^ … ^ a[j-1] = C ,那麼 a[j] ^… a[k] 的值也必須等於 C,否則,兩者異或的值就不等於 0
class Solution {
public int countTriplets(int[] arr) {
int n = arr.length, cnt = 0;
for (int i = 0; i < n; i++) {
int a = arr[i];
for (int j = i + 1; j < n; j++) {
a ^= arr[j];
if (a == 0)
cnt += j - i;
}
}
return cnt;
}
}
複雜度分析
- 時間複雜度:,
- 空間複雜度:,
還有更優的做法嗎?
方法四:前綴和 + map
佛樂…
代辦...
複雜度分析
- 時間複雜度:,
- 空間複雜度:,