异或
参考:http://blog.csdn.net/u012050154/article/details/51957530
Q:给出M个正整数,其中M-1个出现了偶数次,1一个出现了奇数次,找出这个数。
被问到这个问题的时候,我说,把这M各数存在哈希表中,就可以找到那个出现奇数次的数了。然而,这并不是一个好的解法,面试官提示异或。(以下是摘自网络的知识)
1.按位与(&)【有0则0】
运算规则:0&0=0;0&1=0;1&0=0;1&1=1;
用途:
(1)清零。如果想将一个单元清零,只需与一个各位都为0的数值相与即可。
(2)取出一个数的指定位。与上 一个指定位为1,其余位为0的数值即可。
例:设x=11101100,取x的低四位。令x&00001111=00001100
2.按位或(|)【有1则1】
运算规则:0|0=0;0|1=1;1|0=1;1|1=1;
用途:
(1)常用来对某些位置1。或上 一个指定位为1,其余位为0的数值即可。
例:设x=11101100,将x的低四位置1。令x|00001111=11101111
3.异或(^)【同0异1】
运算规则:0^0=0;0^1=1;1^0=1;1^1=0;
用途:
(1)使特定位翻转,异或上 一个要翻转位数为1,其余位为0的数值即可。
例:设x=11101100,将x的低四位翻转。令x^00001111=11100011
(2)与0异或,保留原值。
(3)基于异或运算,不引用新变量,交换两个变量的值
a=a^b;b=a^b;a=a^b(基于加减法还有:a=a+b;b=a-b;a=a-b)
所以,该编程题的解法是:
public class FindOdd {
public static void main(String[] args) {
int[]a={1,1,4,4,4,5,5};
for(int i=1;i<a.length;i++){
a[0]=a[0]^a[i];
}
System.out.println(a[0]);
}
}
Q2:找出一串数中出现了奇数次的两个数。
思路:
这串数中的所有数字异或,结果必定是出现奇数次的那两个数异或的值,并且不为0,记为resExclusiveOR;
找出resExclusiveOR的第一个为1的那个位,记为indexOf1,将数组中indexOf1位为1的数分为一组num1,indexOf1位为0的数分为一组num2;
分别对num1、num2中的数做异或,其结果就是要找的那两个数。(附代码,源自网络)
public class FindOdd {
static void findOnce(int[]data,int length){
int num1=0;
int num2=0;
if(length<2)
return;
int resExclusiveOR = data[0];
for(int i=1;i<length;i++){
resExclusiveOR^=data[i];
}
int indexOf1 = findFirstBitIs1(resExclusiveOR);
for(int i=0;i<length;i++){
if(isBit1(data[i],indexOf1)){
num1=num1^data[i];
}else{
num2=num2^data[i];
}
}
System.out.println(num1+" "+num2);
}
static int findFirstBitIs1(int r){
int indexBit=0;
while((r&1)==0&&(indexBit<32)){
r=r>>1;
indexBit++;
}
return indexBit;
}
static boolean isBit1(int num,int index){
if(((num>>index)&1)==1)
return true;
else
return false;
}
public static void main(String[] args) {
int[]arr={1,4,4,1,6,6,6,7,8,8,8,7};
findOnce(arr,12);
}
}
17.11.9
(1)计算某个正整数中二进制表示中1的个数
方法1:
public static void main(String[] args) {
int n=7;
int count=0;
while(n>0) {
if((n&1)==1) {
count++;
}
n=n>>1;
}
System.out.println(count);
}
但是该解法存在一个问题:
(补充:
右移:00001010>>2=00000010;10001010>>3=11110001
左移:00001010<<2=00101000;10001010<<3=01010000)
方法 2:
private static int countBit(int num){
int count = 0;
for(; num > 0; count++)
{
num &= (num - 1);
}
return count;
}
参考:
http://www.cnblogs.com/hapjin/p/5839797.html
http://www.cnblogs.com/graphics/archive/2010/06/21/1752421.html
(2)判断某个数的第 i 位是0还是1
private static boolean getBit(int num,int b) {
return ((num & (1 << b)) != 0);
}