算法思想总结:位运算

news2024/9/30 1:25:59

                                               创作不易,感谢三连支持!!

一、常见的位运算总结

标题

 

 

二、位1的个数

. - 力扣(LeetCode)

 利用第七条特性:n&(n-1)干掉最后一个1,然后每次都用count++去统计,直到变成0

class Solution {
public:
    int hammingWeight(uint32_t n) 
    {
      int count=0;
      while(n)
      {
        n&=(n-1);
        ++count;
      }    
      return count;
    }
};

 三、汉明距离

. - 力扣(LeetCode)

      利用异或相同为0相异为1的特点,x和y异或后不一样的位都会变成1,这个时候再用n&(n-1)去统计1个个数,即为这两个数字的汉明距离

class Solution {
public:
    int hammingDistance(int x, int y) 
    {
      //异或的特点,相同为0,相异为1     然后再利用n&(n-1)统计1的个数
      int n=x^y;
      int count=0;
      while(n)
      {
        n&=(n-1);
        ++count;
      }
      return count;
    }
};

 四、比特数记位(典型dp)

思路1:每遍历一个数都用n&(n-1)去数他一共有多少个1,然后放心ans数组中

class Solution {
public:
   int countOnes(int x)
   {
    int ones=0;
    while(x)
    {
        x&=(x-1);
        ++ones;
    }
    return ones;
   }
    //利用
    vector<int> countBits(int n) 
    {
       vector<int> ret(n+1);
       for(int i=1;i<=n;++i)  ret[i]=countOnes(i);
       return ret;
    }
};

 思路2:动态规划思想(本质是根据位运算的性质通过已经计算出来的状态去求未计算的状态)

         即当计算 i 的「一比特数」时,如果存在 0≤j<i,j 的「一比特数」已知,且 i和 j 相比,i 的二进制表示只比j多了一个 1,则可以快速得到 i 的「一比特数」。(利用位运算的性质)

1、设置最低位

        对于n(n-1),本质上是将最右侧的1干掉,所以一定会比原来的n小!!

因此bit[i]=bit[i&(i-1)]+1  恒成立!!

class Solution {
public:
  
    vector<int> countBits(int n) 
    {
       vector<int> ret(n+1);
       for(int i=1;i<=n;++i)  ret[i]=ret[i&(i-1)]+1;
       return ret;
    }
};

 2、最低有效位

      对于正整数x来说,如果是偶数的话,右移一位正好就是x/2,并且1的个数不会变,所以偶数bit[i]=bit[i/2]   对于奇数来说,右移一位会丢掉后面的1,所以要给他补上去,所以奇数等于bit[i]=bit[i/2]+1       为了修正奇数多出来的1,我们可以利用i&1,如果是奇数就是1,偶数就是0,因此   bit[i]=bit[i/2]+(i&1) 恒成立!!

class Solution {
public:
  
    vector<int> countBits(int n) 
    {
       vector<int> ret(n+1);
       for(int i=1;i<=n;++i)  ret[i]=ret[i/2]+(i&1);
       return ret;
    }
};

3、最高有效位

       对于正整数 x,如果可以知道最大的正整数 y,使得 y≤x,y 是 2的整数次幂,则 y的二进制表示中只有最高位是 1,其余都是 0,此时称 y 为 x 的「最高有效位」。令 z=x−y,显然 0≤z<x,则 bits[x]=bits[z]+1,所以我们使用heightbit作为当前的最高有效位。如果i&(i-1)为最高有效位,就更新heightbit,i 比 i−highBit的「一比特数」多 1    所以bit[i]=bit[i-height]+1 恒成立!!

class Solution {
public:
  
    vector<int> countBits(int n) 
    {
       vector<int> ret(n+1);
       int heightbit=0;
       for(int i=1;i<=n;++i)  
       {
        if((i&(i-1))==0)  heightbit=i;
        ret[i]=ret[i-heightbit]+1;
       }
       return ret;
    }
};

五、只出现一次的数字(1)

. - 力扣(LeetCode)

思路:利用异或的性质,出现两次的数异或后为0,出现一次的数异或0还是本身 

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
         int n=0;
         for(auto &e:nums)  n^=e;
         return n;
    }
};

六、只出现一次的数字(2) 

. - 力扣(LeetCode)

class Solution {
public:
    int singleNumber(vector<int>& nums) 
    {
        int ret=0;
        for(int i=0;i<32;++i)
        {
            int sum=0;
            for(int num:nums)  if((num>>i)&1) ++sum;//统计个数每一个1的比特位
            sum%=3;//模3后代表ret当前bit位的值
            if(sum==1) ret|=(1<<i);//sum==1就让ret该位置变成1
        }
        return ret;
    }
};

七、只出现一次的数字(3)

class Solution {
public:
    vector<int> singleNumber(vector<int>& nums) 
    {
       unsigned int temp=0;//遇到INT_MIN会溢出,10000……00
       for(int num:nums) temp^=num;
       int x=temp&(-temp);//x拿到最后一个1
       //int x= (temp == temp ? temp : temp & (-temp));
       int type1=0,type2=0;
       for(int num:nums) if(num&x) type1^=num; else type2^=num;
       return {type1,type2};
    }
};

八、丢失的数字

. - 力扣(LeetCode)

思路1:利用等差数列和的公式-数组每一位数相加,即可得到消失的数

class Solution {
public:
    int missingNumber(vector<int>& nums) 
    {
        int n=nums.size();
        return n*(n+1)/2-accumulate(nums.begin(),nums.end(),0);
    }
};

 思路2:利用异或的特点,让0和数组所有数进行异或,再对1-n异或,出现两次的数都会被消去,最后只会留下答案

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

思路3:暴力快排+寻找下标和数字对应不上的数 

class Solution {
public:
    int missingNumber(vector<int>& nums) 
    {
        sort(nums.begin(),nums.end());
        int n=nums.size();
        for(int i=0;i<n;++i) if(nums[i]!=i) return i;
        return n;
    }
};

九、消失的两个数字

. - 力扣(LeetCode)

该题就是只出现一次数组(1)和 (3)的结合,所以以上的思路去解答即可

class Solution {
public:
    vector<int> missingTwo(vector<int>& nums) 
    {
      int temp=0;
      for(auto e:nums) temp^=e;
      for(int i=1;i<=nums.size()+2;++i) temp^=i;
      int x=temp&(-temp);//拿到最右边的1
      int num1=0,num2=0;
      for(auto e:nums) if(e&x) num1^=e;  else  num2^=e;
      for(int i=1;i<=nums.size()+2;++i) if(i&x) num1^=i;  else  num2^=i;
      return {num1,num2};
    }
};

十、判定字符是否唯一

. - 力扣(LeetCode)

 

class Solution {
public:
    bool isUnique(string astr) 
    {
       if(astr.size()>26)  return false;//鸽巢原理做优化
       //利用位图的思想
       int bitmap=0;
       for(auto ch:astr)
       {
        int i=ch-'a';//找到映射关系
        if((bitmap>>i)&1==1)  return false;//先判断该字符是否出现过 判断第i位是否是1
        //如果没出现过,将第i位的0修改为1
        bitmap|=(1<<i);
       }
       return true;
    }
};

十一、或运算的最小翻转次数

. - 力扣(LeetCode)

class Solution {
public:
    int minFlips(int a, int b, int c) 
    {
        int ret=0;//记录翻转次数
      for(int i=0;i<31;++i)
      {
        //找到每一位进行判断
        int bit_a=(a>>i)&1;
        int bit_b=(b>>i)&1;
        int bit_c=(c>>i)&1;
        //情况1,如果c为0的话,那么a和b必须全是0 所以他们是多少就要翻转几次
        if(bit_c==0) ret+=(bit_a+bit_b);
        //情况2,如果c为1的话,那么a和b至少要有一个为1    如果都为0,翻转一次,如果有1就不用翻转
        else ret+=(bit_a+bit_b==0);
      }
      return ret;
    }
};

十二、两整数之和

. - 力扣(LeetCode)

class Solution {
public:
    int getSum(int a, int b) 
    {
       //要考虑-1,因为-1的右移操作是没有定义的
       while(b)
       {
        int  x=a^b;
        int carry=(a&b)<<1;
        a=x;
        b=carry;
       }
       return a;
    }
};

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1540947.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

目标检测——PP-YOLOv2算法解读

PP-YOLO系列&#xff0c;均是基于百度自研PaddlePaddle深度学习框架发布的算法&#xff0c;2020年基于YOLOv3改进发布PP-YOLO&#xff0c;2021年发布PP-YOLOv2和移动端检测算法PP-PicoDet&#xff0c;2022年发布PP-YOLOE和PP-YOLOE-R。由于均是一个系列&#xff0c;所以放一起解…

【算法与数据结构】 C语言实现单链表队列详解

文章目录 &#x1f4dd;队列&#x1f320; 数据结构设计&#x1f309;初始化队列函数 &#x1f320;销毁队列函数&#x1f309;入队函数 &#x1f320;出队函数&#x1f309;获取队首元素函数 &#x1f320;获取队尾元素函数&#x1f309; 判断队列是否为空函数&#x1f309;获…

学习ReentrantLock 原理

ReentrantLock 与 synchronized 锁的实现&#xff1a;synchronized 是 JVM 实现的&#xff0c;而 ReentrantLock 是 JDK 实现性能&#xff1a;新版本 Java 对 synchronized 进行了很多优化&#xff0c;synchronized 与 ReentrantLock 大致相同使用&#xff1a;ReentrantLock 需…

tauri应用实现一键快速更新版本

tauri应用实现一键快速更新版本 创建一个项目 pnpm create tauri-app根据配置选择就可以 pnpm tauri dev启动项目 ##更新配置 打包配置在src-tauri/tauri.conf.json 修改打包命令 "bundle": {"active": true,"targets": "all",&qu…

石子合并与果子合并:区间动态规划和贪心

果子合并是如何将一堆果子合并起来所消耗体力最少&#xff0c;石子合并也是将一堆石子合并起来质量最小&#xff0c;但不同的是 石子合并只能相邻的两个合并 。本篇通过讲解这两个相似例题&#xff0c;来学习区间dp与贪心。 目录 石子合并&#xff1a; 题目&#xff1a; 思路…

Dr4g0n

信息收集 # nmap -sn 192.168.56.0/24 -oN live.nmap Starting Nmap 7.94 ( https://nmap.org ) at 2024-03-04 08:52 CST Nmap scan report for 192.168.56.2 Host is up (0.00012s latency). MAC Address: 00:50:56:FE:B1:6F (VMware) Nmap scan report …

【Redis】Redisson实现分布式锁

Redisson是一个在Redis的基础上实现的Java驻内存数据网格&#xff08;In-Memory Data Grid&#xff09;。它不仅提供了一系列的分布式的Java常用对象&#xff0c;还提供了许多分布式服务&#xff0c;其中就包含了各种分布式锁的实现。 官网地址 GitHub地址 Redisson入门 1.引…

docker安装ES7.1.1(单机版)+ik分词器+es-head可视化

系列文章目录 文章目录 系列文章目录前言 前言 前些天发现了一个巨牛的人工智能学习网站&#xff0c;通俗易懂&#xff0c;风趣幽默&#xff0c;忍不住分享一下给大家。点击跳转到网站&#xff0c;这篇文章男女通用&#xff0c;看懂了就去分享给你的码吧。 Elasticsearch 是一…

海外媒体发稿:7款爆款标题生成器解析-华媒舍

科普文章是将科学知识普及给大众的一种方式&#xff0c;而一个引人入胜的标题往往是吸引读者的第一步。在科普领域中&#xff0c;标题的吸引力至关重要。以下将介绍7款风靡科普界的爆款标题生成器&#xff0c;帮助你创作出引人入胜的科普文章。 1. 情感引爆 情感是人类行为中的…

卷积篇 | YOLOv8改进之主干网络中引入可变形卷积DConv

前言:Hello大家好,我是小哥谈。可变形卷积模块是一种改进的卷积操作,它可以更好地适应物体的形状和尺寸,提高模型的鲁棒性。可变形卷积模块的实现方式是在标准卷积操作中增加一个偏移量offset,使卷积核能够在训练过程中扩展到更大的范围,从而实现对尺度、长宽比和旋转等各…

QML 布局管理器之GridLayout 项目demo

一.气体控制效果图 二.界面布局代码实现 //DottedLline.qml 虚线绘制 import QtQuick 2.12 import QtQuick.Shapes 1.12Shape {id:canvaswidth: parent.widthheight: parent.heightShapePath{strokeStyle: ShapePath.DashLinestartX: 8startY: 10dashPattern: [1, 3]PathLine{…

多线程和线程同步

文章目录 进程和线程线程的操作线程创建线程退出线程回收线程分离线程取消和ID比较 线程同步互斥锁死锁读写锁条件变量信号量 进程和线程 线程是轻量级的进程&#xff0c;在Linux环境下线程的本质还是进程。 在计算机上运行的程序是一组指令及指令参数的组合&#xff0c;指令按…

Web前端-JS

JavaScript&#xff0c;简称js&#xff1a;负责网页的行为&#xff08;交互效果&#xff09;。是一门跨平台&#xff0c;面向对象的脚本语言&#xff08;编写出来的语言不需要编译&#xff0c;通过浏览器的解释就可以运行&#xff09; JS引入方式 1.内嵌样式 这样打开页面就会…

毕业答辩PPT模板涵盖多种风格,包括母版的设计及主题色的设计

毕业答辩PPT模板涵盖多种风格&#xff0c;包括母版的设计及主题色的设计 前言一两个页面的展示研究内容主题概述主题内容一&#xff1a;主要面向三点研究内容主题内容二&#xff1a;主要面向两点研究内容主题内容三&#xff1a;主要面向包含应用开发的研究 前言 之前做了有关开…

Oracle Data Guard部署

Oracle的主备DG搭建 1. 修改主机名,同步时间 主库IP&#xff1a;192.168.100.137 备库IP&#xff1a;192.168.100.138配置主机名(主库) Hostname zygjpdb vim /etc/hosts 192.168.100.137 zygjpdb 192.168.100.138 zygjsdbvim /etc/sysconfig/network HOSTNAMEzygjpdb ------…

电脑如何关闭自启动应用?cmd一招解决问题

很多小伙伴说电脑刚开机就卡的和定格动画似的&#xff0c;cmd一招解决问题&#xff1a; CtrlR打开cmd,输入&#xff1a;msconfig 进入到这个界面&#xff1a; 点击启动&#xff1a; 打开任务管理器&#xff0c;禁用不要的自启动应用就ok了

机器学习算法那些事 | 使用Transformer模型进行时间序列预测实战

本文来源公众号“机器学习算法那些事”&#xff0c;仅用于学术分享&#xff0c;侵权删&#xff0c;干货满满。 原文链接&#xff1a;使用Transformer模型进行时间序列预测实战 时间序列预测是一个经久不衰的主题&#xff0c;受自然语言处理领域的成功启发&#xff0c;transfo…

C语言分支和循环

目录 一.分支 一.if 二.if else 三.if else嵌套 四.else if 五.switch语句 二.循环 一.while (do while&#xff09;break : 二.for函数&#xff1a; 三.goto语句: 四.猜数字: 一.分支 一.if if要条件为真才执行为假不执行而且if只能执行后面第一条如果要执行多条就…

Java基础之关键字instanceof(七)

简介&#xff1a; CSDN博客专家&#xff0c;专注Android/Linux系统&#xff0c;分享多mic语音方案、音视频、编解码等技术&#xff0c;与大家一起成长&#xff01; 优质专栏&#xff1a;Audio工程师进阶系列【原创干货持续更新中……】&#x1f680; 优质专栏&#xff1a;多媒…

【C语言】linux内核pci_iomap

一、pci_iomap /** pci_iomap 是一个用于映射 PCI 设备的 BAR&#xff08;Base Address Register&#xff0c;基地址寄存器&#xff09;的函数。* 此函数返回指向内存映射 IO 的指针&#xff0c;用于直接访问 PCI 设备的内存或 I/O 空间。* * 参数:* dev - 指向pci_dev结构的指…