美文网首页
数组中数字出现的次数

数组中数字出现的次数

作者: 是新来的啊强呀 | 来源:发表于2020-06-09 21:01 被阅读0次

    要求:一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
    异或性质:
    1、两个数字异或的结果a ^ b是将 a 和 b 的二进制每一位进行运算,得出的数字。 运算的逻辑是如果同一位的数字相同则为 0,不同则为 1。
    2、任何数和本身异或则为 0
    3、任何数和 0 异或是 本身
    4、异或满足交换律。 即 a ^ b ^ c ,等价于 a ^ c ^ b
    思路: 这一题如果对全员进行异或的话,由于数组中存在着两个数字不重复的情况,我们将所有的数字异或操作起来,最终得到的结果是这两个数字的异或结果:(相同的两个数字相互异或,值为0)) 最后结果一定不为0,因为有两个数字不重复。
    因此,如果我们可以把所有数字分成两组,使得:
    1)两个只出现一次的数字在不同的组中;
    2)相同的数字会被分到相同的组中。
    那么对两个组分别进行异或操作,即可得到答案的两个数字。

    通过 & 运算来判断一位数字不同即可分为两组,这样那么我们随便两个不同的数字至少也有一位不同!

    public int[] singleNumbers(int[] nums) {
            int sum=0;
            //将数组所有元素进行异或,最后的结果一定是那两个不同数字的异或结果。
            //用示例[4,4,6,1]最后的抑或结果就是 6和1异或的结果 7
            for (int i = 0; i <nums.length ; i++) {
                sum^=nums[i];
            }
            int first = 1;
            // 两个不同数字进行异或的结果为sum,由于位中相同值的异或结果为0(1^1=0),为了使两个只出现一次的数字在不同的组中;所有需要找到sum中数值不同的那一位,也就是sum&first!=0的first,作为分组依据。
            //通过与运算找到result第一个不为0的首位,7=>0111,也就是第一位,第二位和第三位也能作为
            while((sum&first)==0){
                first=first<<1;
            }
            //first为1,所以我们可以根据数组元素的二进制低位第一位是否为1,将数组分为2类,
            // 示例数组可以分为     低位第一位为0:[4,4,6]     低位第一位为1:[1]
            //此时再将两个数组两两异或就可以得到最终结果。
            int result[]=new int[2];
            for(int i=0;i<nums.length;i++){
                //将数组分类。
                if((nums[i]&first)==0){
                    result[0]^=nums[i];
                }
                else{
                    result[1]^=nums[i];
                }
            }
            return result;
        }
    
    

    相关文章

      网友评论

          本文标题:数组中数字出现的次数

          本文链接:https://www.haomeiwen.com/subject/lggetktx.html