📌  相关文章
📜  在未排序的数组中找到奇数出现的两个数字(1)

📅  最后修改于: 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
总结

这个算法利用了异或运算的性质,时间复杂度较低,适用于数组中只有两个出现奇数次的情况,不能用于只有一个出现奇数次的情况。