1.之前知识复习
1).求二进制某位数是1or0,用其与&1or0,
例如,1100100看齐从右向左第五位是0or1,就1100100&10000 结果为0,则为02
public class wei {
public static void main(String[] args) {
// TODO Auto-generated method stub
System.out.println(100&16);
}
}
2).异或可以理解为不进位加法,参考半加器
3).若要交换两位数据a,b。即做三次异或,
int a=20;
int b=30;
//a=10100 b=11110
a=a^b;//a=01010
b=a^b;//b=10100
a=a^b;//a=11110
2.例题
题目:1-1000放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次.每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?
思想:本题的核心便是异或两个相同的数字为0,而随机的数字加数组内容和数组位置有三个,即得数字本身
public class wei {
public static void main(String[] args) {
int n=11;
int[]a=new int[n];
for(int i=0;i<n-1;i++) {
a[i]=i+1;
}
a[a.length-1]=new Random().nextInt(1,n-1);//进行赋值
int index=new Random().nextInt(1,n);//随机找到一个位置插入数组
for(int i=0;i<n;i++) {
System.out.print(a[i]);
}
//查看数组
Until.swap(a,index,a.length-1);
for(int i=0;i<n;i++) {
System.out.print(a[i]);
}
System.out.println();
int x=1;
for(int i=0;i<n;i++) {
x=x^a[i];
}//异或数组内容1-10,还有随机的a【10】
//本题的核心便是异或两个相同的数字为0,而随机的数字加数组内容和数组位置有三个,即得数字本身
for(int i=1;i<n-1;i++) {
x=x^(i+1);
}//异或位置1-10
System.out.println(x);
}
}
题目:任意输入一个数,求其二进制有几个一,例如:输入9(二进制为1001),则有两个“1”.
方法1
核心代码:
if ((n & (1 << i)) == (1 << i)) count++;
核心思想:将“1”进行位运算,并将其对输入数进行与运算。
int main() {
int n = 0;
scanf("%d", &n);
//printf("")
int count = 0;
for (int i = 0; i < 32; i++) {
if ((n & (1 << i)) == (1 << i)) //还可以将输入数反向方向位运算,进行与1的比较
count++;
}
printf("%d", count);
}
方法2
核心思想;
x&(x-1)消除最小的一位“1”,如73(1001001)&72(1001000)为1001000 末位“1”,消去。
int main() {
//方法二
int n = 0;
scanf("%d", &n);
int count = 0;
while (n != 0) {
n = (n - 1) & n;
count++;
}
printf("%d\n", count);
}
题目:交换二进制位的奇偶数位
核心思想:用二进制的0xaaaaaaaa和0x55555555进行数据保留和交换
int x = 9;
int a = 0xaaaaaaaa;//10101010......1010 保留偶数位
int b = 0x55555555;//0101......0101 保留奇数位
int c = x & a;//10101010......1010 保留偶数位
int d = x & b;//0101......0101 保留奇数位
int e = (d << 1) ^ (c >> 1);//c只能向右走 若往左走则最头上的“1”保留的数据丢失
printf("%d", e);