【 异或 位运算】 offer56-1 数组中数字出现的次数

题目

一个整型数组 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]

思路

  1. 两个不同的数字异或结果肯定会有位数是1,两个相同的数字异或结果是0
  2. 循环数组进行异或,最后的结果就是两个不同数字异或的结果
  3. 设置mark,用来记录为1的位数。与异或结果进行&运算,最后得到的结果就是一个全部为0只有一位为0的数字,相当与是记录了为1的位数(会有好几个,有一个就行)。即表示两个不同的数字在位数上不同的位置
  4. 将所有数字与mark进行与运算,如果结果是0,说明该为不是1,分为一组,如果结果是1,说明该位是1,分为一组。相同的数字一定在同一组会抵消,那么两边各自剩下的数字就是不同的数字
  5. 位运算总结
    • 乘除——n<<1 n*2 ; n>>1 n除2
    • 奇偶判断——n&1==1 奇数(其实类似于将与1进行与运算,就将数字分成两类。那么和别的数字进行与运算,也可以分成两类)

代码

public int[] singleNumbers(int[] nums) {
        int res = 0;//存储所有数字异或的结果
        for(int num:nums){
            res ^=num;
        }
        //相同的数字为0抵消,此时的res是两个不同的数异或出来的结果
        //找到两个数字不同的位数,也就是为1的位,会有很多个,找到一个就可以
        int mark = 1;
        while((res&mark)==0){
            mark<<=1;
        } //mark中的1就是不同的位置
        //分成两组
        int a = 0;
        int b = 0;
        for(int num:nums){
            //把该位是0的放到一组,剩下的放到一组。重复的数字会抵消,剩下的就是两个不同的数字
            if((num & mark)==0){
                a^=num;

            }else{
                b^=num;

            }

        }
        return new int[]{a,b};
    }
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值