位运算有五种:与、或、异或、左移、右移;
与(&):两个都为1时才为1;其他都为0。
或(|):有一个为1就为1;其他为0.
异或(^):两个相同为0,不同为1.
左移(>>):左移n位,则高位(左边)去掉n,低位(右边)补0.相当于乘以n个2.
右移(>>):右移n位,无符号位整数:去掉低位(右边)的n位,高位补0.
有符号整数:正数:去掉低位n位,左边补0.负数:左边补1(负数在计算机中二进制呈补码形式:补码,正数二进制,按位取反,加1)。右移相当于除以n个2.
题目:正数n的二进制中1的个数。
解法一:可以用与1(1的二进制中1的前面全是0)做与运算来判断n的最低位是不是为1 ,接着把1左移一位得到2(0010),在与n做为运算,就能判断n的次位是不是为1,如此反复,即可求出1的个数。
代码如下:
//求一整数中的二进制表示1的个数 ,循环次数为整数二进制的位数,如果32位,则循环32次
static int NumberOf1(int n) {
int num = 0;
int falg = 1;
while(falg!=0) {
if((n&falg)!=0)
num++;
falg = falg<<1;
}
return num;
}
第二种算法:
把一个整数减去1,再和原来的整数做与运算,会把该整数二进制表示的最右边的一个1变为0.那么一个整数的二进制中有多少个1,就可以进行多少次这样的运算。
基于这种思想,代码如下:
//优质算法,有几个1,循环几次
static int NumberOf1Nice(int n) {
int num = 0;
while(n!=0) {
num++;
n = (n-1) & n;
}
return num;
}
输入两个整数n和m,计算需要改变m的二进制表示多少位才能得到n,比如10的二进制位1010,13的二进制为1101,需要改变1010中的三位才能得到1101。
解决此问题的方法:可以先做m与n的异或运算,在求出1的个数,即为改变了m二进制的多少位。
扩展问题:
在Excel2003中,用A表示1第一列,用B表示2第二列……用Z表示第二十六列,用AA表示第二十七列,用AB表示第二十八列….以此类推。写出一个函数,输入用字母表示的列号编码,输出他的列号,如输入AA,输出27.
解法:题目本质是把十进制数字用A~Z表示成了二十六进制的了
代码如下:
static int index(String str) {
int index = 0;
if(str == null) {
return -1;
}
String excel = "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
int slen = str.length();
for(int i=0;i<str.length();i++){
//如果输入ABC,先A开始
char x = str.charAt(i);
//如果出现小写字母,输入错误,直接退出,A=65 Z=90
if(x<65 || x>90 ) return -1;
for(int j=0;j<excel.length();j++) {
//求出C所表示的权重(即列号+1,+1因为数组是从0开始编号的)
if(x==excel.charAt(j)) {
//index : ABC = 1*26^2 + 2*26^1 + 3*26^0
index += (j+1)*Math.pow(26, --slen);
break;
}
}
}
return index;
}