在面试当中,你有时可能会很疑惑,明明我答出了题目,为什么对方还是不满意。其实理由往往很简单,你的答案未必是别人要的答案,或者说并不是最好的答案,换而言之,不仅要做出来题目,还要尽可能的考虑算法的效率,也就是通常所说的时间和空间复杂度。其中不少算法题目,还是有套路可言的,今天提到的算法题和位运算(bit twiddling)有关。
高级的编程语言往往能让我们直接访问变量的位,而计算机本身内部就是二进制的表示,所以对位操作,对计算机而言当然是极有效率,再此之前,请关注C#中的一些位运算符 &(AND 与)、|(OR 或)、 ^(XOR 异或)、~(NOT 取反)、 <<(左移位)、>> (右移位),其中移位操作可以很快地乘以2或除以2的次方。 在做题之前,首先记住,和2有关的题目很可能需要使用位运算来计算
问题1:请写一个方法判断一个整数是奇数还是偶数。
分析: 如果答案就是下面这个方法
- //判断一个整数是否是偶数
- public static bool IsEven(int number)
- {
- return ((number % 2) == 0);
- }
貌似我也就不用多费口舌了,这样的问题,学过编程的应该都能写出来。
既然我们已经提到位运算,当然要关注一下奇数和偶数究竟有何不同,奇数的最后一位总是1,比如奇数3,二进制形式为00000011(省略前面24个0),而偶数的最后一位总是0,比如偶数6,二进制形式为00000110。所以我们现在只要检测数字的最低位是否为0,就可以知道它是不是偶数了。
那么,怎么判断最低位是0呢?通常的方案是将最低位和1相与,如果结果为0,则为偶数,否则为奇数
比如奇数3和1位与,实际上是
00000000 00000000 00000000 00000011
&00000000 00000000 00000000 00000001
---------------------------------------------
00000000 00000000 00000000 00000001
再比如偶数6和1位与,实际上是
00000000 00000000 00000000 00000110
&00000000 00000000 00000000 00000001
---------------------------------------------
00000000 00000000 00000000 00000000
所以我们的最终答案可能如下
- /// <summary>
- /// 判断一个整数是否是偶数
- /// </summary>
- /// <param name="number">传入的整数</param>
- /// <returns>如果是偶数,返回true,否则为false</returns>
- public static bool IsEven(int number)
- {
- return ((number & 1) == 0);
- }
- /// <summary>
- /// 判断一个整数是否是奇数
- /// </summary>
- /// <param name="number">传入的整数</param>
- /// <returns>如果是奇数,返回true,否则为false</returns>
- public static bool IsOdd(int number)
- {
- return !IsEven(number);
- }
好的,既然你已经对位运算有了一定的了解,让我们来看下一案例
问题2:请写一个方法判断一个整数是否是2的n次方