当前位置: 首页 > news >正文

位运算刷题+总结

文章目录

  • 判定字符是否唯一
    • 题解
    • 代码
  • 丢失的数字
    • 题解
    • 代码
  • 两整数之和
    • 题解
    • 代码
  • 只出现一次的数字 II
    • 题解
    • 代码
  • 消失的两个数字
    • 题解
    • 代码
  • 总结

判定字符是否唯一

题目链接
在这里插入图片描述

题解

1. 哈希表,创建26个空间大小的哈希表
2. 位图,小写字符只有26个,位图可以存32个0或1,(bitMap >> i) & 1 判断是否存在元素,bitMap |= (1 << i)把元素加入到位图中

代码

class Solution 
{
public:
    bool isUnique(string astr) 
    {
      // 位图
      // >26个字符说明存在重复的字符了
      // 优化
      int n = astr.size();
      if(n > 26) return false;

      int bitmap = 0;
      for(auto ch : astr)
      {
        int i = ch - 'a';
        // 判断是否存在重复元素
        if((bitmap >> i) & 1) return false;
        // 不存在重复的元素就加入到位图中
        bitmap |= (1 << i);
      }
      return true;
    }
};

丢失的数字

题目链接
在这里插入图片描述

题解

1. 哈希表,开大小为n+1的空间,把所有的数加入到哈希表中,如果这个数没有出现,就是丢失的数
2. 高斯求和,(首项加尾项)* 项数 /2 - 数组中元素的和3
3. 位运算,用一个变量异或0到n的所有的数,再和数组中的数异或,就可以找到缺失的数

代码

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

两整数之和

题目链接
在这里插入图片描述

题解

1. a ^ b无进位相加,(a & b) << 1进位,直到进位为0,就是答案

在这里插入图片描述

代码

class Solution 
{
public:
    int getSum(int a, int b) 
    {
        // 异或(无进位相加) &并且左移一位求进位,进位到下一位上
        // 直到进位为0,就时最终答案
        int k = (a & b) << 1;
        int sum = a ^ b;
        while(k)
        {
           a = sum;
           b = k;
           // 无进位相加
           sum = a ^ b;
           // 进位
           k = (a & b) << 1;
        }
        return sum;
    }
};

只出现一次的数字 II

题目链接
在这里插入图片描述

题解

1. 每个数都出现了3次,有3n个数,和只存在一个的数的某个比特位相加,再模3就是和只出现一次的数的比特位是一样的
2. 因此只需要算出数组中每个数的二进制的每个位的加和,再模3就是只出现一次的那个数的每个二进制位

在这里插入图片描述

代码

class Solution 
{
public:
    int singleNumber(vector<int>& nums) 
    {
        int bit = 0;
        int n = nums.size();
        for(int j = 0;j <= 31;j++)
        {
            int sum = 0;
            for(int i = 0;i < n;i++)
            {
                if(((nums[i] >> j) & 1) == 1) sum++; 
            }
            sum %= 3;
            if(sum == 1) bit |= (1 << j);
        }
        
        return bit;

        // map<int,int> ret;
        // for(auto x : nums) ret[x]++;
        // for(auto y : nums)
        // {
        //     if(ret[y] == 1) return y;
        // }   
        // return -1;
    }
};

消失的两个数字

题目链接
在这里插入图片描述

题解

1. 根据x位的不同,如何划分为两类异或?
如果x位上为1的是一组,x为上是0的是一组
比如:第二组样例
010 010
011 011
001 100

001 ^ 100 = 101
x = 1
第一位上为1的是一组,是0的是一组
010 010 100 -> 100
011 011 001 -> 001
这样就得到了答案

在这里插入图片描述

代码

class Solution 
{
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
        // 1.先找出消失两个数异或的结果
        // 2.再分开消失的两个数
        // 这两个数异或的结果肯定不会是0,至少有一位是1
        // 那就根据这位划分为两类异或
        // 划分为这位是1的和0的

        int sum = 0;
        int n = nums.size();
        for(int i = 1;i <= n+2;i++) sum ^= i;
        for(int i = 0;i < n;i++) sum ^= nums[i];
         
        // 提取这个1
        int tmp = sum & (-sum);
        int k = 0;
        for(int i = 0;i < 32;i++) 
        {
            if((tmp >> i) & 1)
            {
                k = i;
                break;
            }
        }

        int m = 0,t = 0;
        
        for(int i = 0;i < n;i++)
        {
            if((nums[i] >> k) & 1) m ^= nums[i];
            else t ^= nums[i];
        }
        for(int i = 1;i <= n + 2;i++)
        {
            if((i >> k) & 1) m ^= i;
            else t ^= i;
        }
        return {m,t};
        
        // vector<int> ret;
        // int hash[30010] = {0};
        // int n = nums.size();
        // for(int i = 0;i < n;i++)
        // {
        //     hash[nums[i]]++;
        // }
        // for(int i = 1;i <= n+2;i++) 
        // {
        //     if(hash[i] == 0) ret.push_back(i);
        // }
        // return ret;
    }
};

总结

1. 给你一个数n,确定这个数的二进制表示上的第x位是0还是1?
(n>>x) & 1,== 0就是0,==1就是1
2. 将一个数n的二进制表示的第x位修改为1?
n = n | (1 << x)
3.将一个数n的二进制表示的第x为修改为0?
n = n & ~(1 << x)
4. 提取一个数n二进制表示中的最右侧的1?
n & (-n) 左侧被n取反后再按位与之后都变成了0,1的右侧都加1都变成了0
5. 干掉一个数n二进制表示中最右侧的1?
n & (n-1) 减一之后会向左边借1,借位的位置变为了0,它的右侧都变成了1,再按位与之后包括它本身都会变成0
6. 异或运算的规律
0 ^ a = a
0 ^ 0 = 0
a ^ a = 0

7. 位图总结
位图可以看成可以存32个二进制位的数组,(bitMap >> i) & 1 判断这一位是否存在,如果存在就加入到位图中,bitMap |= (1 << i)
8. 基础位运算
& | ^ ~ >> <<
9.运算符的优先级
如果判断不了运算符的优先级,就直接加括号

相关文章:

  • CCF-CSP备考【模拟考试系统共享】
  • 用python批量生成文件夹
  • c++介绍运算符重载九
  • 熨斗底板不平?矫平机让每寸布料都平整服帖
  • 21 | 全面测试项目功能
  • C++20 新特性总结
  • 【Vue】el-dialog的2种封装方法(父子组件双向通信),$emit触发父事件/.sync修饰符双向绑定
  • go GRPC学习笔记
  • 《鸿蒙系统下AI模型训练加速:时间成本的深度剖析与优化策略》
  • 位运算性质
  • L3-1 夺宝大赛
  • 【RAG从入门到精通系列】【RAG From Scratch 系列教程5: Retrieval】
  • 动态规划-第2篇
  • Java volatile 关键字详解
  • 华为HCIE认证用处大吗?
  • Python 字节码深度历险:dis 模块揭秘与性能优化实战
  • 数智读书笔记系列016 从《理解和改变世界》探寻AI时代的知识与智能密码
  • 命令行重启Ubuntu软件
  • 云服务器安装宝塔面板部署
  • Mac安装Neo4j图数据库
  • 上交所五方面落实募资新规:强化关键少数责任和股东权利保障
  • 李峰已任上海青浦区委常委
  • 李公明︱一周书记:当前科学观中的盲点、危机与……人类命运
  • 小耳朵等来了春天:公益义诊筛查专家走进安徽安庆
  • 智能手表眼镜等存泄密隐患,国安部提醒:严禁在涉密场所使用
  • 港股持续拉升:恒生科技指数盘中涨幅扩大至6%,恒生指数涨3.3%