1.在处理中整型数值的时候,可以直接对组成整型数值的各个位进行操作,这就意味着可以使用屏蔽技术获得正数中的各个位(?,?)
可以使用屏蔽技术获得整数中的各个位
&(与)、|(或)、^(取反)、~(非)
>>、<<运算符将二进制进行右移或者左移操作
>>>运算符将用0填充高位; >>运算符用符号位填充高位,没有<<<运算符,对应int型,1<<35与1<<3是相同的而左边的操作数是long型的时候需要对右侧操作数模64
2.位运算的技巧:
①判断奇偶数
与1进行与运算,为1时为奇数,为0时为偶数
②获取二进制位是0还是1
③交换两个整数变量的值
例如a = 10100001,b = 00000110
a = a ^ b // a = 10100111
b = b ^ a // b = 10100001
a = a ^ b // b == 00000110
④不用判断语句求出整数的绝对值
2.问题描述:(下面是使用异或来消除重复的元素)
1-1000这1000个数字放在含有1001个元素的数组中,只有唯一的一个元素重复,其他均只出现一次,每个数组元素只能访问一次,设计一个算法,将它找出来;不用辅助空间,能否设计一个算法实现?
连续的数字异或可以消除重复
A^A = 0
(A^A)^B^(C^C) = B
但是我们的题目中是有两个元素重复,假如使用一次异或那么这个重复的元素就会被消除掉了,所以我们使用到一个小技巧来解决这个问题,使用两次异或的方法,那么重复的元素就会出现三次,那么就会消掉一个,其余不重复的元素均为两个,所以都被笑掉了,剩下的那个就是我们要求的那个重复的数字
代码如下:
import java.util.Random;
public class 唯一成对的数 {
public static void main(String[] args) {
int N = 11;
int arr[] = new int[N];
for(int i = 0;i<arr.length;i++){
arr[i] = i + 1;
}
arr[arr.length-1] = new Random().nextInt(N-1)+1;
int index = new Random().nextInt(N);
Utils.swap(arr,index,arr[arr.length-1]);
for(int i = 0;i<arr.length;i++){
System.out.print(arr[i]+" ");
}
System.out.print("\n");
int x1 = 0;
for(int i = 1;i<=N-1;i++){
x1 = (x1^i);
}
for(int i = 0;i<N;i++){
x1 = x1^arr[i];
}
System.out.println(x1);
}
}
Utils类为另外一个包的类,用来生成有一个重复元素的数组,代码如下:
public class Utils{
public static void swap(int[] arr, int index, int j) {
for(int i = 0;i<arr.length;i++){
if(j==arr[i]){
arr[i] = arr[index];
break;
}
}
}
}
除了上面的解法,我们通常的解法是借助辅助空间的办法来求解,
int helper[] = new int[11];
for(int i = 0;i<helper.length;i++){
helper[arr[i]]++;
}
for(int i = 0;i<helper.length;i++){
if(helper[i]==2){
System.out.print(i);
break;
}
}
还有一种方法是使用两重循环:
for(int i = 0;i<arr.length;i++){
for(int j = 0;j<i;j++){
if(arr[i]==arr[j]){
System.out.print(arr[i]);
break;
}
}
}