剑指 Offer 56 - I. 数组中数字出现的次数

Posted 小布丁value

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了剑指 Offer 56 - I. 数组中数字出现的次数相关的知识,希望对你有一定的参考价值。


https://leetcode-cn.com/problems/shu-zu-zhong-shu-zi-chu-xian-de-ci-shu-lcof/

 public int[] singleNumbers(int [] nums){
        //因为相同的数字异或是0,任何数字与0异或的结果就是其本身
        //所以遍历异或或者整个数组的到的结果就是两个只出现一次的数字异或的结果:即 z=x^y
        int z=0;
        for(int i: nums) z^=i;
        //根据异或的性质可以知道:z中至少有一位是1,否则x和y就是相等的
        //我们通过一个辅助变量 m来保存z中哪一位为1(可能有多个位都为1,我们找到最低位的1即可)
        //举个例子: z= 10^ 2 =1010^0010=1000,第四位为1
        //我们将m初始化为1.如果(z&m)的结果等于0说明z的最低位是0
        //我们每次将m左移一位 然后跟z做与操作,知道结果不为0
        //此时m应该等于1000,同z一样,第四位位1
        int m=1;
        while((z&m)==0) m<<=1;
        //我们遍历数组,将每个数与m进行操作,结果为0的作为一组,结果不为0的作为一组
        //例如对于数组:[1,2,10,4,1,4,3,3],我们把每个数字跟1000做与操作,可以分为下面两组:
        //nums1存放结果为0的: [1, 2, 4, 1, 4, 3, 3]
        //nums2存放结果不为0的: [10] (碰巧nums2中只有一个10,如果原数组中的数字再大一些就不会这样了)
        //此时我们发现问题已经退化为数组中有一个数字只出现了一次
        //分别对nums1和nums2遍历异或就能得到我们预期的x和y
        int x=0,y=0;
        for(int i:nums){
            //这里我们是通过if..else将nums分为了两组,一边遍历一边异或
            //跟我们创建数组的num1和num2原理是一样的
            if((i&m)==0) x ^=i;
            else y^=i;
        }
        return new int[]{x,y};
    }

以上是关于剑指 Offer 56 - I. 数组中数字出现的次数的主要内容,如果未能解决你的问题,请参考以下文章

1787. 使所有区间的异或结果为零 / 剑指Offer56 - I. 数组中数字出现的次数 / 剑指Offer56 - II. 数组中数字出现的次数 II / 剑指Offer57.和为s的两个数字(

剑指Offer56 - I. 数组中数字出现的次数(位运算)

算法剑指 Offer 56 - I. 数组中数字出现的次数 重刷太难了

每日一题 - 剑指 Offer 56 - I. 数组中数字出现的次数

剑指 Offer 56 - I. 数组中数字出现的次数

LeetCode(剑指 Offer)- 56 - I. 数组中数字出现的次数