剑指offer40--数组中只出现一次的数字

题目描述

一个整型数组里除了两个数字之外,其他的数字都出现了两次。请写程序找出这两个只出现一次的数字。

思路

思路1: 哈希
先遍历一遍建立hashmap,再遍历一遍找出来

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        map<int,int> m;
        for (int val:data)
        {
            m[val]++;
        }
        
        vector<int> ii;//存储一次出现数字的位置
        for (int i=0;i<data.size();i++)
        {
            if (m[data[i]]==1)
                ii.push_back(i);
        }
        *num1=data[ii[0]];
        *num2=data[ii[1]];
    }
};

思路2: 位运算
利用异或性质:
1.n^n=0;
2.n^0=n;

class Solution {
public:
    void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
        int xor1=0;
        for (int val:data)//将所有数字异或一遍,得到的结果就是数组中两个不同数字的异或结果(性质1)
            xor1^=val;
            
        //不同数字一定存在至少一位不同,我们找到这个不同位来进行分组
        int pos_1=1;
        while((pos_1&xor1)==0)//从右到左找到第一个不同位
            pos_1<<=1;
        
        for (int val:data)//根据第一个不同位置进行分组
        {
            if ((pos_1&val)==0)
                *num1=(*num1)^val;
            else
                *num2=(*num2)^val;
        }
    }
};

为了更好理解根据第一个不同位置进行分组 ,举一个例子:

12233454
00010010001000110011010001010100

异或之后的结果:xor1=0100(即1和5的异或结果)
这样右边第一个不同的位置:pos_1=0100
再将pos_1分别与原来数组的每一个数字:
其中,与1,2,3都为0,这时将他们都异或起来,得到1(因为2,3都有两个);
与4,5都为1,这时也将他们都异或起来,得到5(因为4有两个)。
这样我们就找到了这两个不同的数字。

注意点

在coding的时候,突然发现自己对运算符的优先级又差不多忘光了,比如在上面的:

while((pos_1&xor1)==0)

写的时候缺了与的括号,一直出错,后来才反应过来。
如果不加括号,由于等于==判断优先级要比按位与&优先级高,因此会先判断等于再与。
c++运算符优先级大全

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值