位运算chapter1+⅓:全1函数与其实例

文章介绍了全1函数getOne,它通过位运算高效地计算正整数或无符号整数的2的幂次减1。该算法以O(loglog(n))的时间复杂度工作,通过位移操作实现,理论和实践上都优于浮点运算中的log2。另一个函数pow2uper则用于找到大于等于给定数n的最小2的幂,考虑了n非幂和是幂两种情况。
摘要由CSDN通过智能技术生成

全1函数介绍:

class Solution {
public:
	int getOne(int n) {
		n |= n >> 1;
		n |= n >> 2;
		n |= n >> 4;
		n |= n >> 8;
		n |= n >> 16;
		return n;
	}
};

这个算法只适用于正整数或无符号整数

这个算法的原理就是把一个数的补码的最高位1不断向右复制
例:
以无符号整数2147483648为例
他的补码为: 

1000 0000 0000 0000 0000 0000 0000 0000

 n|=n>>1;

  10000000 00000000 00000000 00000000 (2147483648)
| 01000000 00000000 00000000 00000000 (2147483648>>1)
---------------------------------------
  11000000 00000000 00000000 00000000 (n|n>>1)

n|=n>>2;

  11000000 00000000 00000000 00000000 (更新第一次后的n)
| 00110000 00000000 00000000 00000000 (n>>2)
-----------------------------------------
  11110000 00000000 00000000 00000000 (n|n>>2)

 以此类推,每一次都会复制一次原先的1到后面的位上,而一个数的二进制位数一共是logn个
而这个算法是在二进制位上进行的复制操作,每一次操作过后1都会翻倍占据。
因此,这个算法的时间复杂度是以2为底的O(loglog(n))但是基本可以视为O1的时间复杂度

在数值上,这个算法所计算出来的值是2的(log(n)+1)次幂-1
但对于负数来说,结果一定是-1
利用这个数值上的特性,使用内置函数log2可以实现以一个真O1时间复杂度的代码

int getOne(int n) {
	return (1 << ((int)log2(n) + 1)) - 1;
}

但是请注意,从理论上讲,位运算一般都比浮点运算要快,因为位运算是直接作用在数的二进制表示形式上。尽管log2是高效的,但是log2涉及浮点运算,而浮点运算更复杂,涉及到位表示的解析、指数和尾数的运算等,因此,尽管从时间复杂度上来说使用log2的实现略胜一筹,但实际情况下,这个实现的性能可能与单纯使用位运算的实现平分秋色。

实例:

输出大于等于n的最小的2的幂
输入格式:n>0,n为整数。

int pow2uper(int n) {
	n--;
	n |= n >> 1;
	n |= n >> 2;
	n |= n >> 4;
	n |= n >> 8;
	n |= n >> 16;
	return n++;
}

针对这个解决,一共有两种情况需要处理:

①n不是2的幂,n--不会改变这个数的二进制位数,所以经过全1化之后,n会变成2的(log(n)+1)次幂-1,然后再加1就得到大于等于n的最小的2的幂

②n是2的幂,结果就是n本身,n--先降位,然后全一化n会变成2的(log(n))次幂,然后再加1得到结果。

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值