本文参考《程序员面试金典》
1.位操作原理与技巧
第一组:
-x^000..000 = x ;
- x^111..111 = ~x;
- x^x = 0;
第二组:
- x&000..000 = 0;
- x&111..111 = x;
- x&x = x;
第三组:
- x|000..000 = x;
- x|111..111 = 111..111;
- x|x = x;
理解上述三组原理的含义,我们需要记住所有操作都是按位进行的,某一位的运算结果不会影响其余位 。也就是说,只要上述语句对某一位成立,则同样适用于一串位。
2.常见的位操作
①:获取某一位
假设获取第r位(从右边开始计数),我们将1开始左移r位,得到形如00010000..类似的串,然后执行位与操作。
代码如下:
public boolean getBit(int num,int location)
{
return ((num&(1<<location)!=0));
}
②:置位
先将1左移location位,接着用这个值和num进行“位或”操作,这样只会改变i位的数据。
代码如下:
public int setBit(int num,int location)
{
return num|(1<<location);
}
③:清零
与“置位”操作相反:
public int clearBit(int num,int location)
{
return num&(~1<<location);
}
//下面是将num的最高位至i位清零的做法如下:
public int clearBitsMSBthroughI(int num,int i)
{
int mask = (1<<i)-1;
return num&mask;
}
//将第i位至最后一位清零做法:
public int clearlowertoI(int num,int i )
{
int mask = ~((1<<i)-1);
return num&mask;
}
3.一道试题
要求如下:
分析:一个串中,增加了一个1,就得减少一个1,而增加1的那个位置如果高于减少的位置,那么是满足条件的略大值,否则就是略小值。其次,我们进行起始操作的位置,肯定是为0的位置。
import java.util.*;
public class CloseNumber {
public int[] getCloseNumber(int x) {
// write code here
int[] a = new int[2];
a[1] = getbig(x);
a[0] = getsmall(x);
return a;
}
public int getbig(int x)
{
int c0 = 0;
int c11= 0;
int temp1 = x;
int temp2 = x;
//得到拖尾0的个数
while((temp1&1)==0&&(temp1!=0))
{
c0++;
temp1>>=1;
}
//得到拖尾0左边1的个数
while(((temp1&1)==1)&&(temp1!=0))
{
c11++;
temp1>>=1;
}
int p =c0+c11;
temp2|=(1<<p); //最右边非拖尾0置为1
temp2&=~((1<<p)-1);//p右方所有位清零
temp2|=(1<<(c11-1))-1;
return temp2;
}
public int getsmall(int x)
{
int temp1 = x;
int temp2 = x;
int c1 = 0;//拖尾1的个数
int c00 = 0;//拖尾1左边连续0的个数
while((temp1&1)==1){
c1++;
temp1>>=1;
}
while((temp1&1)==0&&(temp1!=0)){
c00++;
temp1>>=1;
}
int p = c1+c00;
temp2&=((~0)<<(p+1));
int mask = (1<<(c1+1))-1;
temp2|=mask<<(c00-1);
return temp2;
}
}
源码地址:我的github。