文章目录
- 题目
- 标题和出处
- 难度
- 题目描述
- 要求
- 示例
- 数据范围
- 解法一
- 思路和算法
- 代码
- 复杂度分析
- 解法二
- 思路和算法
- 代码
- 复杂度分析
题目
标题和出处
标题:数组异或操作
出处:1486. 数组异或操作
难度
1 级
题目描述
要求
给你两个整数, n \texttt{n} n 和 start \texttt{start} start。
定义数组 nums \texttt{nums} nums,其中 nums[i] = start + 2 × i \texttt{nums[i]} = \texttt{start} + \texttt{2} \times \texttt{i} nums[i]=start+2×i(下标从 0 \texttt{0} 0 开始)且 n = nums.length \texttt{n} = \texttt{nums.length} n=nums.length。
返回 nums \texttt{nums} nums 中所有元素按位异或的结果。
示例
示例 1:
输入:
n
=
5,
start
=
0
\texttt{n = 5, start = 0}
n = 5, start = 0
输出:
8
\texttt{8}
8
解释:数组
nums
\texttt{nums}
nums 为
[0,
2,
4,
6,
8]
\texttt{[0, 2, 4, 6, 8]}
[0, 2, 4, 6, 8],
0
⊕
2
⊕
4
⊕
6
⊕
8
=
8
\texttt{0} \oplus \texttt{2} \oplus \texttt{4} \oplus \texttt{6} \oplus \texttt{8} = \texttt{8}
0⊕2⊕4⊕6⊕8=8,其中
⊕
\oplus
⊕ 为按位异或运算符。
示例 2:
输入:
n
=
4,
start
=
3
\texttt{n = 4, start = 3}
n = 4, start = 3
输出:
8
\texttt{8}
8
解释:数组
nums
\texttt{nums}
nums 为
[3,
5,
7,
9]
\texttt{[3, 5, 7, 9]}
[3, 5, 7, 9],
3
⊕
5
⊕
7
⊕
9
=
8
\texttt{3} \oplus \texttt{5} \oplus \texttt{7} \oplus \texttt{9} = \texttt{8}
3⊕5⊕7⊕9=8。
数据范围
- 1 ≤ n ≤ 1000 \texttt{1} \le \texttt{n} \le \texttt{1000} 1≤n≤1000
- 0 ≤ start ≤ 1000 \texttt{0} \le \texttt{start} \le \texttt{1000} 0≤start≤1000
- n = nums.length \texttt{n} = \texttt{nums.length} n=nums.length
解法一
思路和算法
最直观的方法是遍历数组 nums \textit{nums} nums 中的全部 n n n 个元素,计算按位异或的结果。
由于已知 nums [ i ] = start + 2 × i \textit{nums}[i] = \textit{start} + 2 \times i nums[i]=start+2×i,且数组的长度 n n n 和数组的首个元素 start \textit{start} start 已知,因此不需要显性创建数组,而是可以按照数组的元素值遍历。
代码
class Solution {
public int xorOperation(int n, int start) {
int xor = 0;
for (int i = 0; i < n; i++) {
xor ^= start + 2 * i;
}
return xor;
}
}
复杂度分析
-
时间复杂度: O ( n ) O(n) O(n),其中 n n n 是数组 nums \textit{nums} nums 的长度。需要遍历 n n n 个元素计算按位异或的结果。
-
空间复杂度: O ( 1 ) O(1) O(1)。
解法二
思路和算法
利用按位异或的性质,可以使用 O ( 1 ) O(1) O(1) 的时间得到结果。
根据按位异或的性质,对于二进制表示中的特定位,如果该位出现奇数个 1 1 1 则按位异或的结果是 1 1 1,如果该位出现偶数个 1 1 1 则按位异或的结果是 0 0 0。
由于数组 nums \textit{nums} nums 中的任意两个相邻元素之差都是 2 2 2,因此数组 nums \textit{nums} nums 中的所有元素的奇偶性相同。只有当 n n n 和 start \textit{start} start 都是奇数时,按位异或的结果才是奇数,否则按位异或的结果是偶数。将一个奇数减 1 1 1 的效果是将该奇数的二进制表示的最低位 1 1 1 变成 0 0 0,其余位不变。如果数组 nums \textit{nums} nums 中的所有元素都是奇数,则数组 nums \textit{nums} nums 中的所有元素按位异或的结果(以下简称「数组按位异或结果」)可以通过如下方式计算:将数组 nums \textit{nums} nums 中的所有元素减 1 1 1,得到 n n n 个偶数,计算这 n n n 个偶数的按位异或结果,记为 x x x,如果 n n n 和 start \textit{start} start 都是奇数则数组按位异或结果为 x + 1 x + 1 x+1,否则数组按位异或结果为 x x x。
首先根据 n n n 和 start \textit{start} start 的奇偶性得到数组按位异或结果的奇偶性,如果 start \textit{start} start 是奇数则将 start \textit{start} start 的值减 1 1 1,然后计算 n n n 个连续偶数的按位异或结果。
根据按位异或的性质,对于任意非负整数 k k k, 8 k ⊕ ( 8 k + 2 ) ⊕ ( 8 k + 4 ) ⊕ ( 8 k + 6 ) = 0 8k \oplus (8k + 2) \oplus (8k + 4) \oplus (8k + 6) = 0 8k⊕(8k+2)⊕(8k+4)⊕(8k+6)=0,因此对于任意非负偶数 num \textit{num} num,可以根据 num \textit{num} num 除以 8 8 8 的余数快速计算范围 [ 0 , num ] [0, \textit{num}] [0,num] 中的所有偶数的按位异或结果。
-
如果 num \textit{num} num 除以 8 8 8 的余数是 0 0 0,则从 0 0 0 到 num − 2 \textit{num} - 2 num−2 的所有偶数为若干组 [ 8 k , 8 k + 6 ] [8k, 8k + 6] [8k,8k+6],因此范围 [ 0 , num − 2 ] [0, \textit{num} - 2] [0,num−2] 中的所有偶数的按位异或结果是 0 0 0, [ 0 , num ] [0, \textit{num}] [0,num] 中的所有偶数的按位异或结果是 num \textit{num} num。
-
如果 num \textit{num} num 除以 8 8 8 的余数是 2 2 2,则范围 [ 0 , num − 4 ] [0, \textit{num} - 4] [0,num−4] 中的所有偶数的按位异或结果是 0 0 0, [ 0 , num ] [0, \textit{num}] [0,num] 中的所有偶数的按位异或结果是 ( num − 2 ) ⊕ num = 2 (\textit{num} - 2) \oplus \textit{num} = 2 (num−2)⊕num=2。
-
如果 num \textit{num} num 除以 8 8 8 的余数是 4 4 4,则范围 [ 0 , num − 6 ] [0, \textit{num} - 6] [0,num−6] 中的所有偶数的按位异或结果是 0 0 0, [ 0 , num ] [0, \textit{num}] [0,num] 中的所有偶数的按位异或结果是 ( num − 4 ) ⊕ ( num − 2 ) ⊕ num = ( num − 4 ) + 6 = num + 2 (\textit{num} - 4) \oplus (\textit{num} - 2) \oplus \textit{num} = (\textit{num} - 4) + 6 = \textit{num} + 2 (num−4)⊕(num−2)⊕num=(num−4)+6=num+2。
-
如果 num \textit{num} num 除以 8 8 8 的余数是 6 6 6,则范围 [ 0 , num ] [0, \textit{num}] [0,num] 中的所有偶数的按位异或结果是 0 0 0。
用 xor 1 \textit{xor}_1 xor1 表示范围 [ 0 , start − 2 ] [0, \textit{start} - 2] [0,start−2] 中的所有偶数的按位异或结果(当 start = 0 \textit{start} = 0 start=0 时 xor 1 = 0 \textit{xor}_1 = 0 xor1=0),用 xor 2 \textit{xor}_2 xor2 表示范围 [ 0 , start + 2 × ( n − 1 ) ] [0, \textit{start} + 2 \times (n - 1)] [0,start+2×(n−1)] 中的所有偶数的按位异或结果,用 xor \textit{xor} xor 表示范围 [ start , start + 2 × ( n − 1 ) ] [\textit{start}, \textit{start} + 2 \times (n - 1)] [start,start+2×(n−1)] 中的所有偶数的按位异或结果,则 xor 1 \textit{xor}_1 xor1 和 xor 2 \textit{xor}_2 xor2 可以根据上述方法计算得到, xor \textit{xor} xor 是需要计算的结果。
由于 xor 2 = xor 1 ⊕ xor \textit{xor}_2 = \textit{xor}_1 \oplus \textit{xor} xor2=xor1⊕xor,因此有 xor = xor ⊕ xor 1 ⊕ xor 1 = xor 2 ⊕ xor 1 \textit{xor} = \textit{xor} \oplus \textit{xor}_1 \oplus \textit{xor}_1 = \textit{xor}_2 \oplus \textit{xor}_1 xor=xor⊕xor1⊕xor1=xor2⊕xor1,即 xor \textit{xor} xor 的值等于 xor 2 ⊕ xor 1 \textit{xor}_2 \oplus \textit{xor}_1 xor2⊕xor1。
得到 xor \textit{xor} xor 的值之后,如果 n n n 和 start \textit{start} start 都是奇数则返回 xor + 1 \textit{xor} + 1 xor+1,否则返回 xor \textit{xor} xor。
代码
class Solution {
public int xorOperation(int n, int start) {
int odd = n & start & 1;
start -= start & 1;
return getPrefixXor(start + 2 * (n - 1)) ^ getPrefixXor(start - 2) + odd;
}
public int getPrefixXor(int num) {
if (num <= 0) {
return 0;
}
int remainder = num % 8;
if (remainder == 0) {
return num;
} else if (remainder == 2) {
return 2;
} else if (remainder == 4) {
return num + 2;
} else {
return 0;
}
}
}
复杂度分析
-
时间复杂度: O ( 1 ) O(1) O(1)。
-
空间复杂度: O ( 1 ) O(1) O(1)。