面试题-位操作

 

如何准备:

Bit manipulation can be a scary thing to many candidates, but it doesn’t need to be! If you’re shaky on bit manipulation, we recommend doing a couple of arithmetic-like problems to boost your skills Compute the following by hand: 1010 - 0001 1010 + 0110 1100^1010 1010 << 1 1001^1001 1001 & 1100 1010 >> 1 0xFF - 1 0xAB + 0x11 If you’re still uncomfortable, examine very carefully what happens when you do subtraction, addition, etc in base 10 Can you repeat that work in base 2?

很多应聘者都很害怕“位操作”的题目,害怕确实是没有必要的。如果真的在位操作方面不太擅长的话,建议你还是通过在一些练习好好准备。笔算下面的题目:

如果这些题目做的时候还有困惑的话,那就把我们平时做10进制加减的规则联系到2进制上。

NOTE: The Windows Calculator knows how to do lots of operations in binary, including ADD, SUBTRACT, AND and OR. Go to View Programmer to get into binary mode while you practice.

注意:windows自带的计算器能完成很多2进制下的计算,加减法,求与求门等。点击计算机的“查看” -> “科学型”,再按F7就能进入二进制模式计算了。

Things to Watch Out For:

注意事项:

» It’s really easy to make mistakes on these problems, so be careful! When you’re writing code, stop and think about what you’re writing every couple of lines - or, better yet, test your code mid-way through! When you’re done, check through your entire code » If you’re bit shifting, what happens when the digits get shifted off the end? Make sure to think about this case to ensure that you’re handling it correctly And (&): 0 & 0 = 0 1 & 0 = 0 0 & 1 = 0 1 & 1 = 1 Or (|): 0 | 0 = 0 1 | 0 = 1 0 | 1 = 1 1 | 1 = 1 Xor (^): 0 ^ 0 = 0 1 ^ 0 = 1 0 ^ 1 = 1 1 ^ 1 = 0

*在写代码的时候涉及到位操作一定要小心。边写的时候就要边想下,最好还能测试下。最后全部写完以后再测试一次。
*在做移位操作的时候,特别注意移位超过边界的时候如何处理。一定要想清楚然后。

Left Shift:

左位移:

x << y means x shifted y bits to the left If you start shifting and you run out of space, the bits just “drop off” For example: 00011001 << 2 = 01100100 00011001 << 4 = 10010000

x< < 表示将x向左位移y位。移动时超出的部分直接丢弃。

Right Shift:

右位移:

x >> y means x shifted y bits to the right If you start shifting and you run out of space, the bits just “drop off” the end Example: 00011001 >> 2 = 00000110 00011001 >> 4 = 00000001

x>>y 表示将x向右位移y位。移动时超出的部分直接丢弃。

5 1 You are given two 32-bit numbers, N and M, and two bit positions, i and j Write a method to set all bits between i and j in N equal to M (e g , M becomes a substring of N located at i and starting at j) EXAMPLE: Input: N = 10000000000, M = 10101, i = 2, j = 6 Output: N = 10001010100

5.1 给你两个32位整数N,M,还有表示位置的i和j。实现方法使得N的i至j位等于M。例如:输入  N = 10000000000, M = 10101, i = 2, j = 6 输出 N = 10001010100
5.1解答:
解法很简单,首先将N的i到j位清零,然后再将M左移i位,最后将两数做或。
面试题-位操作_第1张图片

5 2 Given a (decimal - e g 3 72) number that is passed in as a string, print the binary rep- resentation If the number can not be represented accurately in binary, print “ERROR”

5.2 以字符串形式传入一个十进制数(例如3.72),输出它的二进制表示形式。如果不能准确表示则输出"ERROR"
5.2解答:首先我们思考一下小数是如何用二进制表示的。以n = 0.101 = 1 * (1/2^1) + 0 * (1/2^2) + 1 * (1/2^3)为例。
打印输出整数部分是非常简单和直接的。小数部分我则采用将n*2,取整数部分,这就相当于“移位”的思想。

如果r>1,那么说明小数点后第一位为1。一直这样做,我们就能得到小数的二进制表示方法。

(译者注:本题作者理解为若32位小数仍无法表示则认为该数无法用二进制准确表示。更为准确的是判断标准为:在转换的任意阶段,若小数部分的最后一个数字非5,在该数无法被二进制数准确表示。)

5 3 Given an integer, print the next smallest and next largest number that have the same number of 1 bits in their binary representation

5.3 给定一个整数,输出与这整数在二进制表示下有相同个数“1",大于n的最小值和小于n的最大值。
5.3解答:
暴力算法:
最简单的方法就是从n向上/向下例举,判断是否有对应个数的”1“。但是这样的方法一点技术含量也没有。
根据数字性质:
首先观察
* 若降一个”1“变为”0“,再另一个”0“必须变为1;
* 若将第i位的0变为了1,第j为的1变为了0,那么数字大小的变化为2^i - 2^j;
* 若要变大数字必须让i大于j。
求大于n的最小值:
* 将n转化为二进制,从右往左依次遍历各位,在经过1后,遇到的第一个0,将其置1。这样就是个数字增大了2^i。例:xxxxx011100 变成 xxxxx111100
* 将i位右边的1置0,这样数字总的变化2^i-2^(i-1)。例:xxxxx111100 变成 xxxxx101100
* 为了让大于n的最小值,将i-1之后的1都移到最右端。
求小于n的最大值,方法类似:
* 将n转化为二进制,从右往左一次遍历各位,在经过0后遇到的第一个。例如xxxxx100011 变为 xxxxx000011
* 将i位右边的0置为1。例如xxxxx000011 变为 xxxxx010011。
* 为求最大值,将i-1位后的1尽量往左移到。
有了算法,开始着手写代码的时候记得将一些常用的方法放到一个公共的类中,写出整洁的代码。
面试题-位操作_第2张图片

5 4 Explain what the following code does: ((n & (n-1)) == 0)

5.4 解释下面表达式的含义 ((n & (n-1)) == 0)
5.4解答
我们来反向思考这个问题。
A&B=0是什么意思呢?它表示A和B两个数的二进制数每一位都不相同。那么n & (n-1)=0,说明n和n-1也没有相同的位。
那n-1又表示什么意义呢?从下面的例子你能看发现什么呢?

当你做减法的时候,主要看最低位,如果最低位为1,那么最低位直接变0;如果最低位为零,那么向高位借1,再减。从低位开始向高位将0变为1,直到借位的那一位。那么n和n-1的关系将会如下例所示:

如果n&(n-1)为0的话,说明例子中的abcde均为0,也就是说n中只有一位为1。也就是说n为2的整数次幂。

5 5 Write a function to determine the number of bits required to convert integer A to integer B Input: 31, 14 Output: 2

5.5 实现函数计算将整数从A变成B需要变动几位。例如 输入:31,14 输出 2
5.5解答:
本题的解题关键在于发现A和B之间有多少位是不同的。那如何判断A和B那些位不同呢?对XOR!
将获得A和B不同的部分,统计出有多少个1就能判断需要变动几位了。
面试题-位操作_第3张图片

5 6 Write a program to swap odd and even bits in an integer with as few instructions as possible (e g , bit 0 and bit 1 are swapped, bit 2 and bit 3 are swapped, etc)

5.6 实现方法将一个整数中的偶数位和奇数位交换。(例如:将0位和1位交换,2位和3位交换)
5.6解答:
用10101010(0xAA)这样的掩码提取出偶数位的信息,类似的用0x55提取奇数位的信息。然后错位求或即可。

5 7 An array A[1 n] contains all the integers from 0 to n except for one number which is missing In this problem, we cannot access an entire integer in A with a single operation The elements of A are represented in binary, and the only operation we can use to access them is “fetch the jth bit of A[i]”, which takes constant time Write code to find the missing integer Can you do it in O(n) time?

5.7 一个数组A[1,n]能容纳n个数字,现将0到n这n+1个数字,随机的放入到数组中。最后会有一个数字没有进入数组。现在让你找出这个数字。但是有如下的限制,不能直接访问数组的整个元素,只能访问“A[i]的第j位”。写出代码找出该元素。能否将时间复杂度控制在O(n)。
5.7解答:
(译者注:作者这里假设n为奇数。)
首先我们将0到n的所有数字的二进制表达列出来。那么我们可以发现最低位的,大概是这样的情况:count(0)>=count(1)。
如果我们从中移除了一个数字,会怎么样呢?

如果移除的数最低位为0,那么count(1)>=count(0);如果移除的是1,那么count(0)>count(1)。如果n次访问每个数的最低位,那么用以上的准则我们就能判断出没有进入数组的那个数字的最后一位是什么。如果最低位是0的话,那就可以排除最低位为1的元素;如最低位为1,那就可以排除末尾为0的。
那下一步怎么办呢?看次低位的情况?那么我以n=5,未入数组的数字为3。经过上一轮的排除后,剩下的数字如图所示:

那么现在次低位的情况为0 0 1 0 1 0 ,根据之前的逻辑我们知道,次低位应该是1。那么我们继续排除。只保留末尾为11的元素。剩下的就是:

再继续看倒数第三位。同样方法知道第三位应该是0。那么我们确定出了丢失的元素。
根据以上的方法,确定实现代码如下:
面试题-位操作_第4张图片
那算法的时间复杂是多少呢?第一次扫描了N次的最低位,第二次为N/2......以此类推,根据下式子:

所以我的算法的复杂度为O(n)。

你可能感兴趣的:(面试题-位操作)