问题简述:
先简单的解释一下题目:
1. 给定一个数组,求解出该数组中奇数个数的那个数,当然这里我们控制该奇数个数的值只有一个。给定案例如:[1,2,2,2,2,2,2,3,3,3,5,5,5,5.1] 推出 3是我们的想要找的数。
2.给定一个数组,求解出该数组中奇数个数的那个数,当然我们这里控制该奇数个数的值有两个。给定案例如 :[1,2,2,2,2,5,5,5,3,3,3,3] 推出 1 和5 为我们想要找的数
思路分析:
这里我们有几个思路问题:
思路:1.最首先我们想到是把第一个数值拿出来,开始遍历所有的数值,然后对出现的次数计数,如果出现奇数次就直接返回,若没有则自动开始下一个数 的循环上述操作遍历下去。
思路:2.我们这里还有一个很简单的解答方式,就是说我们可以使用异或运算操作来处理该操作,这里我们对于第一个题目和第二个题目还是需要不同的操作。我们首先来说说第一个题目的理解:这里我们可以使用异或运算来进行操作,我们指定一个 数为0,然后不断的异或,若是遇到偶数次的数值就可以默认跳过,最后给我们留下来的也就是奇数次的那个数。 下面我们说说第二问的解答思路,第二问中我们加大了这个题目的难度,也就说我们需要找到两个奇数次的数值,当然这里我们知道根据我们第一步的操作可以全部异或一次,剩下的也就是 我们需要的结果的那两个数的异或操作。在这之后我们需要对他们两个数进行分组操作,他们之前必然存在一位二进制位不相同的情况。故我们只需要找出其中的一位,便可以进行相应的分组操作。具体的分组操作我会在下面的代码中有所体现。我这里描述起来也不是很好描述。
直接上代码:
class comperAandB {
public static void main(String[] args) {
int arr[] = {11, 2, 2, 2, 2, 5, 5, 6};
comper(arr);
}
public static void comper(int[] arr) {
//第一步就可以简单的求解出该数组中的奇数个数的值。
//若是有两个奇数的话,这里的eor必定是 a^b,则可以推出下面的操作。
int eor = 0;
for (int a : arr) {
eor ^= a;
}
/*
* eor = a^b
* eor != 0
* eor 必然还是有一个位置不相同 则表示为1;
* */
//我们下面的操作就是把 a和b分开来找,如何分开 就根据他们之间的某个位置不相同的地方来区别是否为a或者b;
int rightOne = eor & (~eor + 1);//这里就是找出不相同的那个二进制位为1 至少有一个二进制位不相同;
int onlyOne = 0;
for (int curr : arr) {
if ((curr & rightOne) == 0) { // 这里可以换成是1或者 0 都是可以的
onlyOne ^= curr;
}
}
System.out.println(onlyOne);
//这里我们拿到只是其中的一个a 或者 b
//要想拿到别的值我们可以再次 异或操作 相当于 eor = a^b^b;
System.out.println(onlyOne ^ eor);
}
}