二进制位操作的相关算法
-
直接交换整数a,b两个变量的值,不使用其他变量
a = a^b; b = a^b; a = a^b;
更简单的写法:
a ^= b ^= a ^= b
二进制层级的算法内容,主要涉及到位的运算与操作。
二进制的位的基础操作如下:
-
x & (x-1) ,该操作是把x的二进制表示的最低位的1给清零。例如 x = 0b1010110执行上面的语句后x变成0b1010100
-
x & !(x-1)得到最低位的1,例如
x = 0b1010110 x-1 = 0b1010101 !(x-1) = 0b0101010 x & !(x-1) = 0b0000010
于是x二进制表示中,最低位的1我们就取得了。
-
交换第i位和第j位的值(最低位从0开始)
例如:x = 0b0101 ,i = 1,j = 0;交换第i位和第j位后 x = 0b0110;
代码如下
int swapBit(int x ,int i, int j){ if((x >> i)&1 != (x>>j)&1){ // 判断第i位和第j位是否一样 x ^= (1 << i) | (1 << j); //交换第i位和第j位 } return x; }
0b 0 1 0 1 //x的值 0b 0 0 1 1 // (1 << i) | (1 << j)的结果 0b 0 1 1 0 // 亦或操作的结果
-
将64位整形二进制数进行倒转
例如:x = 0b11100倒转后x = 0b00111
基于第四步的位交换操作,很容易实现该功能
int reserve(int x){ int j = Integer.size - 1; int i = 0; while(i < j){ swapBit(x,i,j); x ++; j --; } }
一道算法面试题
对于64位或32位的无符号整形数x,我们把它的二进制表示中,1的个数称为x的权重,例如 x = 7,它的二进制表示为111,那么x的权重就是3,用S(k)表示64位或32位无符号整数中,权重是k的所有整数的集合,其中k不等于0和64, 给定一个整形数x,x属于S(k),要求你找到另一个整形数y 属于S(k),y不等于x,并且使得 |x-y|的值最小。
如果仅仅翻译题目的要求,会陷入困境。
方法:小量数据分析模式,当没有想法的时候可以用几组样例试一下,发现其中的规律。
-
x = 0b1011
y = 0b1101
-
x = 0b11101
y = 0b11011
多试几组就会发现:从最右边往左走,当第一次发现两位不同的时候,交换两位的位置。就会的到满足条件的y。
代码实现如下:
int findMinAbs(int x){
for(int i = 0 ; i < Integer.size ;i++){
if(swapBit(x,i,i+1) != x){//判断相邻两位是否相等
return swapBit(x,i,i+1);
}
}
return x;
}