常见位运算及其经典算法题(1)

常见位运算及其经典算法题(1)

位运算顾名思义,是对整数的二进制位直接进行操作的运算。由此很多算法便有了更优解,大大提高了效率。如果你之前没有接触过位运算或者淡忘了,这篇文章或许会对你很有帮助。

1.六大核心运算符

<<(左移运算符)

规则:左移n位,低位补0

例如:5的二进制为0101,5<<2即0101左移两位,变成010100,即20

所以5<<2==20
我们可以发现:根据二进制转十进制的计算,原数字二进制中整体往左移动n位,就是乘以2^n,所以左移运算符的重要用途就是快速计算乘2的幂。

>>(右移运算符)

规则:右移n位,高位补符号位

例如:5>>1,即0101右移两位,等于0010;

(-5)>>1:

5的二进制位0000 0101(原码),求负数的二进制规则就是它对应的正数取反 ,+1,即

取反:1111 1010;+1:1111 1011。即-5=1111 1011(8位)

所以右移一位即:1111 1101,把它转回十进制,即-1,取反

0000 0011等于3,而根据上文表粗的原则,1111 1101=-3,即-5>>1==-3

&(按位与运算符)

规则:两个整数的每一位二进制比较,两个中有0结果就是0,其他都是1

例如:5(0101)& 3(0011)== 1(0001)

同理>>可以计算x//2^n(向下取整)

||(按位或运算符)

规则:两个整数的每一位二进制比较,两个中有1结果就是1,其他都是0

例如:5(0101)|| 3(0011)== 7(0111)

^(按位异或运算符)

规则:相同位0,相反为1,无进位相加

例如:5(0101)^ 3(0011)== 6(0110)

~(按位取反运算符)

规则:0变1,1变0

2.位运算常用结论

  • 取出二进制第i位:(x >> i)& 1
  • 将第i位改成1:n = n | ( 1 << i )
  • 将第i位改成0:n = n & ( ~ ( 1 << i ) )
  • 提取二进制中最右侧的1:n & ( -n )
  • 将二进制中最右侧的1变成0:n & (n-1)
  • 异或运算律:a ^ 0 = a. a ^ a = 0. a ^ b ^ c=a ^ (b ^c)

3.经典例题

1.leetcode面试题 01.01. 判定字符是否唯一

这道题我们可以用set数据结构快速解决。但还有一种方法,便是位运算。

题中所给字母均为小写,所以一个符合条件的字符串最多包含a-z 26个英文字母。而整型有32位。我们可以从前往后遍历字符串,得出每个字符关于a的偏移量,将对应位的0变成1.代表此字母已经出现,如果后续再出现就返回false

cpp 复制代码
class Solution {
public:
   bool isUnique(string astr) {
       int flag=0;//每一位的0/1便是判断正误的关键
       for(auto e:astr)
       {
           int offset=e-'a';
           if(flag&(1<<offset))//判断此位是否已经为1
           {
               return false;
           }
           flag=flag|(1<<offset);//将此字母存入flag中
       }
       return true;
   }
};

2. leetcode371. 两整数之和

我们看到这道题后,就能大概率猜出是要用到位运算的知识点.

而这里便用到了异或^无进位相加的性质.

例如2^3==1(0001),异或以后惊奇的发现结果就是无进位相加后的结果,所以我们现在只需算出进位,再将两者异或,知道进位为0便可算出结果.

进位的表达式是(a&b)<<1.例如:

算到这里后,再将0001与0100异或得到0101,他俩的进位为0000,即0101就是结果5

cpp 复制代码
class Solution {
public:
    int getSum(int a, int b) {
        while(b!=0)
        {
            int x=a^b;//^的无进位相加
            unsigned int carry=(unsigned int)(a&b)<<1;//记录进位
            a=x;
            b=carry;
        }
        return a;
    }
};

今天就是这些东西。如有疑问,欢迎打在评论区。

主页还有更多优质内容OvO

相关推荐
2401_8846022720 小时前
程序人生-Hello’s P2P
c语言·c++
weixin_4588726120 小时前
东华复试OJ二刷复盘2
算法
Charlie_lll20 小时前
力扣解题-637. 二叉树的层平均值
算法·leetcode
初中就开始混世的大魔王20 小时前
2 Fast DDS Library概述
c++·中间件·信息与通信
爱淋雨的男人20 小时前
自动驾驶感知相关算法
人工智能·算法·自动驾驶
wen__xvn21 小时前
模拟题刷题3
java·数据结构·算法
滴滴答滴答答21 小时前
机考刷题之 6 LeetCode 169 多数元素
算法·leetcode·职场和发展
娇娇yyyyyy21 小时前
C++基础(6):extern解决重定义问题
c++
Neteen21 小时前
【数据结构-思维导图】第二章:线性表
数据结构·c++·算法
礼拜天没时间.1 天前
力扣热题100实战 | 第25期:K个一组翻转链表——从两两交换到K路翻转的进阶之路
java·算法·leetcode·链表·递归·链表反转·k个一组翻转链表