📅  最后修改于: 2023-12-03 15:08:03.484000             🧑  作者: Mango
在一个未排序的数组中,除了某两个数字出现了奇数次外,其他数字均出现了偶数次。请找出这两个数字。
一个整数如果出现了偶数次,那么它们的异或和(XOR)一定为0。因此,我们可以先将整个数组异或一遍,得到的结果就是这两个出现奇数次的数字的异或值。
我们将这个异或值记为xorResult
。由于这两个数字不相同,因此它们的二进制表示中至少有1位是不同的。我们可以找到这个不同的位,将数组中所有二进制表示中这一位为1的数字异或一遍,得到的结果就是其中一个数字;将数组中所有二进制表示中这一位为0的数字异或一遍,得到的结果就是另一个数字。
下面是实现代码:
public void findOddNumbers(int[] nums) {
int len = nums.length;
int xorResult = 0;
// 先异或整个数组
for (int i = 0; i < len; i++) {
xorResult ^= nums[i];
}
// 找到不同的位
int diffBit = 1;
while ((diffBit & xorResult) == 0) {
diffBit <<= 1;
}
// 将数组分为两部分,每部分都包含一个出现奇数次的数字
int num1 = 0, num2 = 0;
for (int i = 0; i < len; i++) {
if ((nums[i] & diffBit) == 0) {
num1 ^= nums[i];
} else {
num2 ^= nums[i];
}
}
System.out.println("两个出现奇数次的数字分别为:" + num1 + " 和 " + num2);
}
这个算法时间复杂度为O(n),空间复杂度为O(1)。
我们用一组数组来测试一下这个算法:
int[] nums = new int[] {1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 1, 2, 3, 4, 5, 6};
findOddNumbers(nums);
输出结果如下:
两个出现奇数次的数字分别为:7 和 8
这个算法利用了异或运算的性质,时间复杂度较低,适用于数组中只有两个出现奇数次的情况,不能用于只有一个出现奇数次的情况。