LeetCode面试题56 - I. 数组中数字出现的次数
异或的性质:
-
交换律:p ⊕ q = q ⊕ p
-
结合律:p ⊕ (q ⊕ r) = (p ⊕ q) ⊕ r
-
恒等率:p ⊕ 0 = p
-
归零率:p ⊕ p = 0
代码如下
/*
* 因为数组中只有两个数是不相同的,其余相同
* 所以将整个数组的元素都取异或,由于异或的结合律,无先后顺序
* 所以最终相同的一对异或成0,最终结果就是两个不同数的异或结果
*
* 相同的数在每一位都是相同的,所以我们要从低位向高位找到
* 两个不同的数是从哪一位开始出现不相同的情况,就是下文的mark的作用
*
* 找到mark后,遍历原数组,用“&”对所有元素在该位置上鉴别
* 分类标准是取与后为0或为1。
* 同理在鉴别过程中,相同的数在mark位上一样也是相同的,取异或只会等于0
*
* Code by Java
*/
class Solution {
public int[] singleNumbers(int[] nums) {
int sum = 0; //将所有的数都取异或
for (int num : nums) {
sum ^= num;
}
int mask = 1; //获取sum中最低位的1;
while((sum & mask) == 0) {
mask <<= 1; //在该位是0,则mask左移一位
}
int a = 0, b = 0; //用于表示数组中不同的两个数
for (int num : nums) {
if((num & mask) == 0) {
a ^= num; //0与任何数取异或都等于任意数本身
} else {
b ^= num; //同理找到另一个数
}
}
return new int[] {a,b};
}
// public static void main(String[] args) {
// int[] aa = new int[] {1,2,3,10,2,2,1,3};
// Solution sol = new Solution();
// int[] kk = sol.singleNumbers(aa);
// for (int i : kk) {
// System.out.println(i);
// }
// }
}