lowbit算法
常用位运算
n >> k & 1 //求n的第k位数字: n >> k & 1 //k是从第0位开始算起, 这里的移位运算符的优先级大于逻辑运算符
n & -n // 返回n的最后一位1的位置(二进制的第几位, 这里相当于补码与上原码
我们常封装一个lowbit函数返回一个数二进制表示的是最低位的 1 及其后边所有的 0 构成的数值。, 例如 6 的二进制表示为 0000 … 0110; 其最低位的1及后面的0构成的数为 10b, 那么lowbit(6) = 2;
auto lowbit(int n) -> int
{
return n & -n;
}
具体说明为啥让一个数和它的负数相与的结果就是该数二进制表示中最低位的 1 及其后边所有的 0 构成的数值。
lowbit算法这里不仅应用于位运算中,还应用于树状数组中。 这里可以应用这个来做一下力扣的一道简答题 : 题目链接 : 191. 位1的个数
代码实现 –> 这里使用了上面的lowbit函数, 但做法多样,这里只是参考
class Solution
{
public:
int hammingWeight(uint32_t n)
{
int cnt = 0;
while(n)
{
int t = n & -n; // t 的结果为 最低位的1和后面的0组成的数值
if(t) ++cnt; // 若结果不为0, 说明存在最低位的1
n -= t; // 将n 减去 t 即使得当前的最低位的1变为0.
}
return cnt;
}
};
位运算实现加减法
相关练习题目 :85. 不用加减乘除做加法
计算机内部的加减乘除运算可以只由与门和或门两个门电路来实现, 故这里的话我们通过数字的运算结果来找下规律
那么对于两个数, 例如 n1, n2, 进行加法运算时,我们可以把它分为两部分相加 :
两个数进行异或的部分 + 两个数相加进位的部分
即 (n1 ^ n2) + ((n1 & n2 ) << 1); 注意这里n1 & n2相与之后的结果我们还需要左移一位,因为进位是向高位进一位的故要左移动, 我们发现这其实也是一个加法,那么我们就继续套娃, 我们令 sum = n1 ^ n2, carry = (n1 & n2 ) << 1; 那么对于这两个数 sum 和 carry的相加,同样分为两部分, 即(sum ^ carry) + ((sum & carry ) << 1); 同样继续套娃, 那么套到啥时候呢, 我们通过观察可以发现第二个加数, 每次都会进行左移一位的操作,即每左移一次, 那么其最低位必然多一个0, 那么当我们的第二个加数为0时,此时 sum + 0 = sum, 此时说明我们的运算已经结束了, 此次加法的结果即为第一个加数, 故其代码实现为:
class Solution
{
public:
int add(int num1, int num2)
{
while(num2) // 当第二个加数不为0时需要继续
{
int sum = num1 ^ num2; // 得到不含进位的加法结果
int carry = (num1 & num2) << 1; // 得到进位的结果
num1 = sum; // num1 更新为不含进位的加法结果
num2 = carry; // num2 更新为相加进位的结果
}
return num1;
}
};