位运算chapter3:判断是否是2的幂的幂------构造掩码法

文章介绍了C++中的四个方法(is2pow,is4pow,is8pow,is16pow)用于检测整数是否为2、4、8、16的幂,利用构造掩码法检查二进制表示中1的位置。这些方法通过位操作快速确定幂次规则,时间复杂度较低。
摘要由CSDN通过智能技术生成
class Solution {
public:
	bool is2pow(int x) {
		if (x <= 0)return 0;
		return (x & x - 1) == 0;
	}
	bool is4pow(int x) {
		if (x <= 0)return 0;
		return (x & x - 1 | x & 0xaaaaaaaa) == 0;
	}
	bool is8pow(int x) {
		if (x <= 0)return 0;
		return (x & x - 1 | x & 0xb6db6db6) == 0;
	}
	bool is16pow(int x) {
		if (x <= 0)return 0;
		return (x & x - 1 | x & 0xeeeeeeee) == 0;
	}
};

时间复杂度O(1)

详细分析每个方法的工作原理:

  1. is2pow 方法:
    brian kernighan算法

  2. is4pow 方法:
    验证是否是4的幂,先确保 x 是2的幂,然后检查1是否在奇数位上,因为4的任何幂的二进制表示将只有一个1,并且1出现在偶数位置上。(从右向左数,最右边的位是第0位)

    • 像 is2pow 方法一样,首先检查 x 是否小于等于0。
    • 接下来检查 x 是否是2的幂,同样使用 (x & (x - 1)) == 0
    • 然后,使用 (x & 0xAAAAAAAA) == 0 判断1是否在偶数位上。0xAAAAAAAA 是一个16进制常数,它的二进制表示为 10101010101010101010101010101010,其中所有1位都处于可能被判定为4的幂次的位置。
  3. is8pow 方法:
    检查8的幂,确保1出现在3的倍数的位置上。

    • 同样的,先进行2的幂检查 (x & (x - 1)) == 0
    • 0xB6DB6DB6 是一个特殊的数,二进制表示为 10110110110110110110110110110110,其中,0的位置都是8的幂的二进制表达式中的‘1’可能出现的位置。
  4. is16pow 方法:
    同理,16的幂验证,确保1出现在4的倍数的位置上。

    • 类似地,它先检查 (x & (x - 1)) == 0
    • 然后,它使用 0xEEEEEEEE(二进制为 11101110111011101110111011101110),其中,0的位置都是16的幂的二进制表达式中的‘1’可能出现的位置。

这类方法是构造掩码法,用一个特定的掩码来检查1的位置是否符合2的幂的幂的规则。这个掩码里的‘1’是用来屏蔽非2的幂的幂的位置的。

这个掩码的构造思路也十分简单,首先找到二的幂的这个数的二进制表达式,比如说32,是100000,然后-2,得到11110,最后把它反复拼接(从11110变成1111011110以此类推),并删去超过数据类型的部分。注意,拼接时一定要进行完整拼接之后超出了数据类型才能删多余的
拼接得到111,1011,1101,1110,1111,0111,1011,1101,1110这才是完整拼接之后的结果
然后再删去得到1011,1101,1110,1111,0111,1011,1101,1110
这个数的16进制表达式是0xbdef7bde

根据这个规律,可以得出一个构造掩码的函数

	unsigned int mask(int x) {
		x = x - 2;
		int bit = log2(x) + 1;
		do {
			x |= x << bit;
			bit <<= 1;
		} while (bit < 16);
		return x |= x << bit;
	}

其中x为2的幂,16的含义是int类型下最高位数(32)的一半这样就可以快速得出对应的掩码了。
时间复杂度O(\log \log x)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值