位运算符知识点
& 与、| 或、^ 异或[二者不同时结果为1]、~非/取反
异或:可以理解为不进位加法:1+1=0、0+0=0、1+0=1
1、>>和<< 将二进制位进行右移或者左移操作
2、 >>>将用0填充高位、>> 用符号位填充高位 没有<<<运算符
性质:
1、对于任何数x,都有xx=0、x0=x,同自己求异或为0,同0求异或为自己
2、自反性ABB=A^0=A,连续和同一个因子做异或运算,最终结果为自己
例题
第一题
1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其它均只出现一次。每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助存储空间,能否设计一个算法实现?
因为不能使用辅助的存储空间,这里方法主要使用^ 这个位运算符进行解决。用到了A^ A=0、 B^0=B中的关系式进行。因为只有一个重复的。因此,在再与1-1000个不重复数进行异或运算的时候,假设重复的数字为K,则会有三个K。此时因为K ^ K=0,最后K^0=K.就会剩下一个重复的元素。
//因为1000个有点长,就只用了11个来写,但其实一样的
int N=11;
int[] arr=new int[N];
for (int i=0;i<arr.length-1;i++){
arr[i]=i+1;
}
//最后一个数是随机数,使其满足某一个数是重复的
arr[arr.length-1]=new Random().nextInt(N-1)+1;
for (int i=0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.println();
int x1=0;
for (int i=1;i<=N-1;i++){
x1=x1^i;
}//1-N没有任何重复自身的异或
for(int i=0;i<N;i++){
x1=x1^arr[i];
}
System.out.println(x1);
但使用这种方法的时候,有一个前提的条件,就是必须已经知道这个数组里面有哪些数值了。不然是不可以进行的,这个时候就需要使用到辅助空间进行运算。
//接着上面的一些参数进行使用
//辅助空间的数组下标用法
int[] helper=new int[N];
for(int i=0;i<N;i++){
//这里因为使用了辅助空间,原来arr[i]就变成了对应的下标,
//因为0-1000的值,对应的下标就也是0-10000这个时候,就可以填入新的数组中,进行+1判断
helper[arr[i]]++;
}
for(int i=0;i<N;i++){
if (helper[i]=