力扣刷题-56 - I. 数组中数字出现的次数、位运算的应用

一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。

c++位运算

  1. 位运算
    计算机中是用二进制存储数据。一个字节包含8个位,每个“1”或者“0”就是一位。
    ①.按位与:&
    两个位都是1结果才是1,只要有一个是0,结果就是0;
a&1== 1//a末尾是1,a是奇数
b&(b-1)//b二进制表示中右边数第一个1变成0

 ②.按位与:|
 两个位只有有一个是1,结果就是1;
 ③.按位异或:^
 两个位相同则结果为0,不同则结果为1;

a^a=0;0^a=a;

 ④.按位取反:~
 1替换成0,0替换成1
 ⑤.左移:<<
 按位顺序向左移动指定位,右端空出位置补0,左端移出位置丢弃

2<<1 结果同2*2,无信息丢弃的情况下,左移一位相当于乘2

 ⑥.右移:>>
 按位顺序向右移动指定位,左端移入位置补0,右端移出位置丢弃

5>>1 结果是2,左移一位相当于除2取整
  1. 运算优先级
    位运算符的优先级低于==

本题分析

  1. 对数组中全员进行异或的结果等于只出现一次的两个数字的异或结果
  2. 两个数字异或后某个位置时1,表示两个数字的该位不同
  3. &运算可以用来判断某位是不是1

代码示例

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        int res = 0;//保存全员异或运算的结果
        for( int i = 0;i < nums.size();i++)
        {
            res = res^nums[i];

        }
        int div = 1;
        //末位开始找第一个是1的位
        while( (div & res )== 0 )//某位和1进行与运算是0,这说明该位是0
        {
            div = div << 1;//左移一位
        }
        //找到了第k个位置是1的数,说明两个数的第k个位置不相同,依次对数据进行分组
        int a = 0;
        int b = 0;
        for( int i = 0;i < nums.size();i++)
        {
            if( div & nums[i]  )//第k个位置是1
            {
                a = a^nums[i];
            }
            else//第k个位置时0
            {
                b = b^nums[i];
            }
        }
        return vector<int>{a,b};
    }
};

力扣刷题-56 - I. 数组中数字出现的次数、位运算的应用_第1张图片

你可能感兴趣的:(力扣刷题,#,位运算,算法与数据结构)