一. 几种运算符的用法
1." ^"
“^”(异或)的使用:不同为1,相同为0
例如:…01011010
…01001101
以上给出的是两个数二进制的片段。我们以这个片段来讲解异或如何运算
根据异或的使用不同为1相同为0可以得出异或的结果为:…00010111
其实只要记住异或的运算就是二进制的无进位相加即可
2." &"
"&"的使用:都为1才得1其余情况都为0
3." |"
" |"的使用:只要有1那么结果就是1否则为0
4.“~”
"~"的使用:取反操作0变1,1变0;
二.运算符相关的几个经典题目及常用性质
题目一
1.让两个不同的数进行交换(不许创建新的变量)
==
解这道题我们要熟悉异或的运算性质:
a^a = 0;
a^0 = a;
异或满足交换律和结合律:a ^ b =b ^ a; (a ^ b) ^ c = a ^ (b^c)
即0和任何数做异或运算都得任何数;两个相同的数做运算得0
所以我,我们就可以来用这个性质来解这道题,代码如下:
public class t {
public static void main(String[] args) {
int a = 2;
int b = 3;
System.out.println("交换前a的值:"+a+" "+"交换前b的值:"+b);
a = a^b;
b = a^b;
a = a^b;
System.out.println("交换后a的值:"+a+" "+"交换后b的值:"+b);
}
}
运行结果:
上述代码中b = a^ b 可以看成 b = (a^ b) ^b 根据结合律的性质可以得出:b =a ^ ( b ^ b)
即b = a;同理可以推导出a就等于b原来的值
题目二
2.给定一个数组只有一种数出现了奇数次其余各种数都出现了偶数次,找出这个数
解题代码:
public class t {
public static void main(String[] args) {
int[] arr = {1,1,1,1,2,2,2,3,3,4,4,7,8,7,8};
int c =0;
for(int i = 0;i<arr.length;i++){
c = c^arr[i];
}
System.out.println(c);
}
}
运行结果:
解题大概思路:把数组所有的数都异或起来相同的数异或解果是0,0异或任何数得任何数,最后得结果就是出现奇次得数了
题目三
3.给定一个数组有两种数出现了奇数次其余各种数都出现了偶数次,找出这两个数
解题代码:
public class t {
public static void main(String[] args) {
int[] arr = {1,1,2,2,3,3,4,4,4,5,5,12,6,6,7,7,8,8};
int a = 0;
for(int i = 0;i<arr.length;i++){
a = a^arr[i];
}
int k = a&(-a);
int c = 0;
for (int j = 0;j<arr.length;j++){
if((k&arr[j])!=0){
c = c^arr[j];
}
}
System.out.println("这两个数分别是:"+c+" "+(a^c));
}
}
运行结果:
解题思路:
假设出现奇次数得两个数分别a,b
第一步:把数组中所有得数都异或起来最后得结果是a^ b;
第二步:判断出a ^b 这个数的二进制最右边第一次出现1的位置
比如一个数的二进制为:…00010100010; 从右到左数第二个位置就是第一次出现1的位置 aa是一个数 将aa进行这样操作 :aa&(-aa),这样就能找的最右变第一次出现1的位置了,假设a ^ b这个数从右数第二个位置第一次出现1 那么对应的·a和b这两个数的二进制第二个位置对应必定是一个位置是0,一个是1;只有这样异或的结果才能是1;
第三步将这个数组分成两组,一组是第二个位置为1的一组是不为1的,那么出现奇次数的两个数就分别在这两组中,然后将这两组数分别异或起来就能得到出现奇数次的那两个数了
题目四
给定一个数组其中有一个数出现了k次其他数都出现了m次 ,其中 1<k<m 找出这个数
解题代码如下:
public class t {
public static void main(String[] args) {
int[] arr = {1,1,1,2,2,2,4,4,4,5,5,5,7,7,8,8,8,0,0};
int[] aa = new int[32];
for(int i = 0; i<arr.length;i++){
int c = arr[i];
for(int j = 0;j<32;j++){
aa[j] = (c&1)+aa[j];
c = c>>1;
}
}
double q = 0;
for (int i = 0;i<aa.length;i++){
if(aa[i]%3!=0){
q = Math.pow(2,i)+q;
}
}
System.out.println((int)q);
}
}
运行结果:
解题思路:
将数组的所有数转成32位的二进制形式然后每一位都加起来然后将加起来的每一位都对m取余,不为零的就是说明在这个位置是出现k次数的二进制位加和的位置进而推导出出现k次的数