问题2:请写一个方法判断一个整数是否是2的n次方
相信你能马上写出如下的算法
- //判断一个整数是否是2的n次方
- public static bool IsPower(int number)
- {
- if (number <= 0)
- {
- return false;
- }
- if ((number & (number - 1)) == 0)
- {
- return true;
- }
- return false;
- }
初学写成这样确实不错,我们用到了位运算,但事实上,貌似和没有用的时候算法效率差不多。(提一个额外的话题,在写程序时尽量使用复合赋值运算符号,比如 i++的效率比 i += 1要高, i += 1 又比 i = i + 1要高)
但再仔细考虑一下,2的n次方会有什么特点?那就是其二进制表示只有1个1,那我们又怎么能知道其二进制表示只有1个1呢?
想了两天,突然想到,如果是整数8,其二进制表示形式是00001000,减去1后为00000111,而这两者位与的结果刚好是0
所以就有了下面的算法
- //判断一个整数是否是2的n次方
- public static bool IsPower(int number)
- {
- if (number <= 0)
- {
- return false;
- }
- while (true)
- {
- if (number == 1)
- {
- return true;
- }
- //如果是奇数
- if ((number & 1) == 1)
- {
- return false;
- }
- //右移一位
- number >>= 1;
- }
- }
- public static void Main()
- {
- Console.WriteLine(IsPower(-8));
- Console.WriteLine(IsPower(0));
- Console.WriteLine(IsPower(1));
- Console.WriteLine(IsPower(2));
- Console.WriteLine(IsPower(5));
- Console.WriteLine(IsPower(9));
- Console.WriteLine(IsPower(12));
- Console.WriteLine(IsPower(16));
- }
这个算法的效率一次循环都没做当然要比上面的高(事实上下面的算法时间复杂度是O(1),而上面的算法时间复杂度是O(n))
好的,让我们更进一步
问题3:对字节变量,其二进制表示法中求有多少个1,如 00101010则返回值为 3,也是要求效率最高