剑指 Offer 56 - I. 数组中数字出现的次数
题目:
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
示例 1:
输入:nums = [4,1,4,6]
输出:[1,6] 或 [6,1]
示例 2:
输入:nums = [1,2,10,4,1,4,3,3]
输出:[2,10] 或 [10,2]
解答:
public class leetCode56 {
public static int[] singleNumbers(int[] nums) {
int ret = 0;
for(int num:nums){
ret ^= num;// ret最终答案就是那两个只出现一次的的数异或的结果 由交换律和结合律所得 而且最终答案一定不等于0
// System.out.println(ret);
}
// 敲黑板,划重点,接下来才是精髓
// 找到ret二进制数中第几位是1 有什么意义呢? 为1 说明a、b两个数在这一位的值肯定不同,一个为0,一个为1
int target = 1;//初始位0001
while((target & ret)==0){//如果target第一个二进制位不为1,就将target左移一位位0010,然后与相与,判断ret第二位是否为一.按此循环,知道找到ret的第一个为1的二进制位
target = target<<1;
System.out.println("target:"+target);
}
int a = 0, b = 0;
for(int num:nums){
if((num & target)==0){//第一组
// 解析:
// 因为target位,一个数为0,一个数为1 所以可以分为两组
// eg: ret为0101 第一位就是1 所以target为2的0次幂为1
// 所以 a、b 两个数,第一位就不同
// 1为0001 4为0100
// 第一组 : 0100 & 0001 == 0
// 第二组 : 0001 & 0001 != 0
a ^= num;
System.out.println("0:"+num);
}else{//第二组
b ^= num;
System.out.println("1:"+num);
}
}
return new int[]{a,b};
}
public static void main(String[] args) {
int[] i = {1,2,3,4,2,3};
singleNumbers(i);
}
}