***剑指 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};
    }
}

 

posted @ 2021-03-26 11:31  星予  阅读(37)  评论(0编辑  收藏  举报