位运算(一):判断一个正整数是否可表示为2的N次方

题目:判断一个正整数num是否可表示为2的N次方。

对于这样一道题目,最简单的做法就是定义一个变量,并让其以2的n(n=0,1,2,3,...)次方递增,每次递增后与num比较,如果相等则返回true,直到递增到大于num,返回false。

/************************************************************************/
/* 
   判断一个正整数num是否为2的N次方(常规解法1)
   算法时间复杂度为O(logN),空间复杂度为O(1)											
*/
/************************************************************************/
bool Is2pow_1(unsigned int num) {	
	unsigned int temp = 1;
	while(temp <= num) {
		if (temp == num) {
			return true;
		}
		temp = temp * 2;
	}
	return false;
}
以下解法2,可以在算法性能上有所提高。(位运算的性能高于乘法运算)

/************************************************************************/
/* 
   判断一个正整数num是否为2的N次方(常规解法2)
   算法时间复杂度为O(logN),空间复杂度为O(1)										
*/
/************************************************************************/
bool Is2pow_2(unsigned int num) {	
	unsigned int temp = 1;
	while(temp <= num) {
		if (temp == num) {
			return true;
		}
		temp = temp << 1; // 位运算比乘法运算性能高,在一定程度提高性能	
	}
	return false;
}
对于以上解法1和解法2,在本质上都是一样的,没有减少算法的时间复杂度。

下面的解法才是真正的算法优化,将时间复杂度降到了O(1)。

/************************************************************************/
/* 
	判断一个正整数num是否为2的N次方
   基本思想:
   十进制		二进制		N-1			N&N-1		是否为2的乘方
     8			 1000		111			  0				是
	16			10000	   1111			  0				是
	32		   100000	  11111			  0				是
   100		  1100100	1100011		  1100000			否
   算法时间复杂度为O(1),空间复杂度为O(1)
*/
/************************************************************************/
bool Is2pow(unsigned int num) {	
	if (num == 0){
		return false;
	}
	return (num & (num-1)) == 0;
}


以上算法,主要是利用与运算进行性能的优化,根据于此,我们可以扩展出如下两个基本的题目:

扩展题目1:给定一个正整数num,求其二进制中"1"的个数。

扩展题目2:给定一个正整数num,求其二进制中"0"的个数。

以上扩展题目的程序代码如下:

/************************************************************************/
/* 
   计算一个正整数num转化为二进制后,"1"的个数。
   基本思想:从右到左依次去除"1",并统计其个数。
   算法的计算次数只与num的位数有关,与其大小无关。
   算法时间复杂度为O(logN),空间复杂度为O(1)												
*/
/************************************************************************/
unsigned int NumberofOne(unsigned int num) {
	int count = 0;
	while (num) {
		num = num & (num-1);
		count++;
	}
	return count;
}

/************************************************************************/
/* 
   计算一个正整数num转化为二进制后,"0"的个数。
   基本思想:从右到左依次与1进行与操作,并统计其个数。
   算法的计算次数只与num的位数有关,与其大小无关。
   算法时间复杂度为O(logN),空间复杂度为O(1)												
*/
/************************************************************************/
unsigned int NumberofZero(unsigned int num) {
	int count = 0;
	while (num) {
		if ((num & 0x01) != 1){
			count++;
		}
		num = num >> 1;
	}
	return count;
}






  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值