***剑指 Offer 56 - I. 数组中数字出现的次数
新的一天开始刷题。
这道题完全没有思路,忘记了异或操作。
思路注释里写的很清晰了,注意&与&&的差别以及最后返回的写法。
补充:
提交没过,错误点在于while((m & n) == 0)写成了while((m & n) != 1)
因为两个数 按位&结果并不是非0即1,只是0和1的&运算结果非0即1。
比如0000 0010 是4
0001 0110 是22
4 & 22 还是4,只是不是0
剑指 Offer 56 - I. 数组中数字出现的次数
class Solution { public int[] singleNumbers(int[] nums) { int n = 0, m = 1; //不重复的两个数字 int x = 0, y = 0; /* * 首先遍历一遍数组取得 x ^ y的值n * 异或操作相等为0,不相等为1 * x与y不相等,则x ^ y必有某一位为1 */ for(int num : nums) n ^= num; /* * 只有1 & 1 == 1,其他情况均为0 * 为了找出上面的n的某一位1,使用1循环左移 & n * 0000 0001 -> 0000 0010 * 此处找到的是 为1的最低位 */ while((m & n) == 0) // & 按位与运算符 &&逻辑与运算符 &优先级高 m <<= 1; /* * 根据找到的为1的那一位,对整个数组进行分组 * 分组条件:1.两个只出现一次的数字在不同的组中;2.相同的数字会被分到相同的组中。 * 1.因为找到的那一位 x ^ y == 1,x和y不相等,分别为1,0。 1 & 1 == 1, 0 & 1 == 0 * 2.相同的数字那一位必定相同,要么都为0,要么都为1 */ for(int num : nums){ // ==优先级高于位运算,需要加括号 if((m & num) == 0) x ^= num; else y ^= num; } //注意返回数组的写法 return new int[]{x, y}; } }