LeetCode_342

题目:

给定一个整数 (32 位有符号整数),请编写一个函数来判断它是否是 4 的幂次方。

本题有题目限制,不能用递归和循环。

解析:

判断一个数是不是4的幂次方,最笨的办法是不断让它除以4,再进行判断,但这种方法要递归或者循环,不符合题意。那么就要用到位运算。4的幂次方有1,4,16,64,256。他们的二进制分别是1,100,10000,1000000,100000000,即一个1后面有偶数个0。而2的幂次方的二进制特点是一个1后面都是0,与4的幂次方的二进制类似,那么我们可以先判断它是不是2的幂次方,再判断是否为4的幂次方。

判断2的幂次方的位运算方法是:a&a-1。比如4,4&3的运算过程为:100&011,将每一位都进行与运算,结果为000,即只要一个数是2的幂次方,则它与它减去1的数进行与运算的结果就是0。

难点在于判断4的幂次方,首先经过之前2的幂次方的判断,将所有1000....形式的数筛选了出来。其中是2的幂次方但不是4的幂次方的数的二进制中,1是在偶数位,例如8,他的二进制为1000。是2的幂次方也是4的幂次方的数的二进制中,1是在奇数位,例如4,他的二进制是100。判断方法就是将这个数和1010101010101010101010101010101做与运算。这串二进制数的特点是1在奇数位0在偶数位,则如果用一个4的幂次方数和它做与运算后,得到的还是这个4的幂次方数。

1010101010101010101010101010101这个数的十六进制是0x55555555,那么最后的程序代码为:

	public boolean isPowerOfFour(int num) {
		if (num <= 0)
			return false;
		if ((num & num - 1) != 0)
			return false;
		if ((num & 0x55555555) == num)
			return true;
		return false;
	}

补充知识:0x为十六进制的标识符,我们经常会见到一些例如0x55555555,0x3333333,0xaaaaaaaa等形式的字符串,其实它们的特殊性在于他们的二进制形式很特殊,例如:

0x55555555 = 1010101010101010101010101010101 (偶数位为0,奇数位为1);

0xaaaaaaaa = 10101010101010101010101010101010 (偶数位为1,奇数位为0);

0x33333333 = 110011001100110011001100110011 (1和0每隔两位交替出现);

0xcccccccc = 11001100110011001100110011001100 (0和1每隔两位交替出现);

0x0f0f0f0f = 00001111000011110000111100001111 (1和0每隔四位交替出现);

0xf0f0f0f0 = 11110000111100001111000011110000 (0和1每隔四位交替出现);

这些二进制非常实用,可以方便得进行位运算,而他们的十六进制更加好记。

猜你喜欢

转载自blog.csdn.net/Q_M_X_D_D_/article/details/82286651