首页 > 编程语言 >算法思想总结:位运算

算法思想总结:位运算

时间:2024-03-24 14:59:28浏览次数:25  
标签:总结 运算 nums int Solution 算法 vector bit public

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

一、常见的位运算总结

标题

 

 

二、位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;
    }
};

标签:总结,运算,nums,int,Solution,算法,vector,bit,public
From: https://blog.csdn.net/weixin_51142926/article/details/136973389

相关文章

  • 【算法双周赛】蓝桥杯【小白赛】
    坤星球【算法赛】问题描述坤星球是一颗十万光年之外的星球,相比于地球的时间流逝它的时间流逝更加缓慢,坤星球1年等于地球2.5年。现在问你,2024坤年等于地球多少年?注意:答案输出阿拉伯数字,不能为浮点数。输入格式本题为填空题,无需输入即可作答。输出格式输出一个数......
  • 机器学习算法那些事 | 使用Transformer模型进行时间序列预测实战
    本文来源公众号“机器学习算法那些事”,仅用于学术分享,侵权删,干货满满。原文链接:使用Transformer模型进行时间序列预测实战时间序列预测是一个经久不衰的主题,受自然语言处理领域的成功启发,transformer模型也在时间序列预测有了很大的发展。本文可以作为学习使用Transformer模......
  • raft算法和etcd代码解析-3.网络分区问题及其它
    网络分区问题网络分区导致选举永远无法达成共识,选举不断超时,任期号将不断增加为避免这个问题,candidate会探测网络环境以免发起无意义的竞选集群变更leader收到配置变更要求,会广播配置变更日志,日志包括新结点和老节点,在收到老节点的多数派认可后,leader后提交该请求在处理配置......
  • Floyd 判圈算法
    概述  Floyd判圈算法又称作是龟兔赛跑算法,就是快慢指针的应用,主要用于判断并找到环形链表的入口。做法是设置两个指针,一个快指针(兔子),一个慢指针(乌龟),快指针一次移动两个节点,慢指针一次移动一个节点。如果有环存在,它们第一次会在环上相遇,这时快指针移动到出发点,转换成慢指针(就是......
  • 蓝桥杯2017年第八届真题-分巧克力(二分算法)
    题目描述儿童节那天有K位小朋友到小明家做客。小明拿出了珍藏的巧克力招待小朋友们。小明一共有N块巧克力,其中第i块是HixWi的方格组成的长方形。为了公平起见,小明需要从这N块巧克力中切出K块巧克力分给小朋友们。切出的巧克力需要满足:1.形状是正方形,边长是整数2.大......
  • TSP旅行商问题——SA模拟退火算法,SA+GA组合算法(代码解释)
    SA代码直接用就行,成功率极高importrandomimportnumpyasnpimportmatplotlib.pyplotasplt#randomlygeneratethemapwithconstraintof[-100,100]defgen_cities(city_num,random_state=True):ifrandom_state:cities=(np.random.uniform(0......
  • 【webserver】 C++ 项目webserver面试八股总结(二)
    32.一次网页的访问从URL开始,说一下整个访问的过程客户端获取URL->DNS解析->TCP连接->发送HTTP请求->服务器处理请求->返回报文->浏览器解析渲染页面->TCP断开连接客户端:(应用层开始)获取URL,通过负责域名解析的域名服务获取网址的IP地址,根据HTTP协......
  • java数据结构与算法刷题-----LeetCode75. 颜色分类
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846文章目录1.双指针两次遍历2.三指针1.双指针两次遍历解题思路:时间复杂度O(......
  • java数据结构与算法刷题-----LeetCode451. 根据字符出现频率排序
    java数据结构与算法刷题目录(剑指Offer、LeetCode、ACM)-----主目录-----持续更新(进不去说明我没写完):https://blog.csdn.net/grd_java/article/details/123063846文章目录1.hash统计出现次数后排序2.桶排序1.hash统计出现次数后排序解题思路:时间复杂度O(......
  • 合同范文文档工作总结等免费下载方法
    发现一款小工具,可以免费下载合同,工作总结等等文档!下载地址如下:https://download.csdn.net/download/weixin_43973655/89020838......