逻辑运算
1.如果想要实现:num * 2+ 1 则可以使用 (num>>)|1
2.实现两个数交换各自的值
public class Logic01 {
public static void main(String[] args) {
int a = 103;
int b = 435;
a = a ^ b;
b = a ^ b;
a = a ^ b;
System.out.println(a);
System.out.println(b);
}
}
解析:(异或的特点:0 ^ 数 = 数; 数^数 = 0)
第一步: a = a ^ b;
第二步: b = a ^ b;//这里可以等价为:b = a ^ b ^ b = a;
第三步 :a = a ^ b;//这时等价:a = a ^ b = ( a ^ b ) ^ a = b ;
3.一个数组中有一个数出现了奇数次,其他都出现了偶数次,如何找到这个数并打印
public class Logic02 {
public static void main(String[] args) {
int[] arr = {1,1,1,1,2,2,2,3,3,4,5,5,4};
int ero = 0;
for (int i = 0; i < arr.length; i++) {
ero ^= arr[i];
}
System.out.println(ero);
}
}
在这里也可以包装成一个方法,可以增加代码复用性
解析:
该问题与上一题运用了同一技巧,因为其他数都为偶次出现,那么,出现了偶数次的数在异或期间,都等于了0,剩下那个出现奇数次的数与0异或得到的也就是这个数;
例如上面这个数组:四个一,三个二,两个三四五,数组中相互异或得到的自然就是这个数
4.一个二进制数,如何取出最右侧的那个一
用到了:int b = a & ( (~a) + 1)
例如:a = 0100110010100 ①
~a = 1011001101011 ②
(~a) + 1= 1011001101100 ③
此时 ①&③ 得到的就是 0000000000100
int a = 18;
int b = a & ((~a) + 1);
System.out.println(Integer.toBinaryString(b));//Inteage 中的方法,toBinaryString用于转换为二进制数
5.一个数组中两个数出现了奇数次,那么其他数出现了偶数次,如何找到并打印这两个数
此时比第三题难度增加很多,但是可以运用第三第四题,进行解决
思路:任然使用第3题的方法,这时ero = 第一个出现奇数次的数 ^ 第二个出现奇数次的数
因为这两个数必然不可能相等,所以此时利用第4题的方法,找到ero中最右侧的1,利用这个位置上的1,将原数组分为两类
一类为该位置上为1,另一类为0
继续使用异或,分别在这两类中进行异或,那么就得到了这两个数
如何利用这个数分类就显得尤为重要,假定这个数为a,a与这个数组中的每个数进行与,为0 ,就说明在此位置上相同,均为1,
public class Logic04 {
public static void main(String[] args) {
int[] arr = {1, 1, 1, 1, 2, 2, 2, 3, 3, 4, 5, 5, 4, 5};
int ero = 0;
for (int i = 0; i < arr.length; i++) {
ero ^= arr[i];
}
int a = ero & ((~ero) + 1);
int b = 0;
for (int i = 0; i < arr.length; i++) {
if ((arr[i] & a) != 0) {
b ^= arr[i];
}
}
System.out.println("一个出现奇数次的数为: " + b + " 另一个出现奇数次的数为: " + (ero ^ b));
}
}