C++ 位运算总结

位运算的运算对象只能是整型或者字符型数据。

C++ 的位运算符:

  • 按位与: &
  • 按位或: |
  • 按位异或: ^
  • 按位取反: ~

C++中的移位运算:
移位运算是指将二进制信息串作为整体移动。

  • 左移运算符: 低位补0,高位被移出来的位抛弃,左移1位在左移没有丢失高位信息的情况下相当于乘以2.
  • 右移运算符: 与左移相反,对于小整数,每右移1位,相当于除以2。在右移时,需要注意符号位问题。对无符号数据,右移时,左端空出的位用0补充。对于带符号的数据,如果移位前符号位为0(正数),则左端也是用0补充;如果移位前符号位为1(负数),则左端用0或用1补充,取决于计算机系统。对于负数右移,称用0 补充的系统为“逻辑右移”,用1补充的系统为“算术右移”。

Leetcode上位运算的几道例题

1、位异或运算
C++ 位运算总结_第1张图片
异或运算: 相同为0,不同为1。将数组中的所有元素求异或和,对于相同的元素,异或的结果为0。因此,数组中成对出现的元素异或和为0,所有元素的异或和即为只出现一次的元素。

class Solution {
public:
    int singleNumber(vector<int>& nums) {
        int ans = nums[0];
        for(int i = 1; i < nums.size(); i++) {
            ans ^= nums[i];
        }
        return ans;
    }
};

2、位异或运算2

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

分析:
有了例题1的经验,我们可以想到:如果将整型数组nums分为两个组,分组满足

  • 两个只出现一次的数字被分到不同的组
  • 相同的数字分到相同的组

那么,只需要对这两个组分别做一次异或和运算,得到的结果就是两个只出现一次的数字。

关键来了,如何进行分组呢?

**取整型数组异或和为1的那一位,为1的分为一组,为0的分为一组,是否满足上面两个条件: **

  • 相同的数字,对应的位肯定相同,因此相同的数字肯定能分到相同的组
  • 因此异或的运算法则是相同为0,不同为1,因此这一位来看,这两个只出现一次的数字的对应位肯定一个是1,一个是0,最终异或的结果才能为1。因此,可以将这两个只出现一次的数字被分到不同的组

代码实现如下:

class Solution {
public:
    vector<int> singleNumbers(vector<int>& nums) {
        // 求异或和
        int ans = nums[0];
        for(int i = 1; i < nums.size(); i++) {
            ans ^= nums[i];
        }

        // 找到异或和结果中为1的那一位
        int div = 1;
        while((ans & div) == 0)
            div = div << 1;
        
        // 分组
        int a = 0, b = 0;
        for(int i = 0; i < nums.size(); i++) {
            if((div & nums[i]) == 0) {
                a ^= nums[i];
            }
            else {
                b ^= nums[i];
            }
        }
        return vector<int>{a, b};
    }
};

你可能感兴趣的:(c++)