转自:https://blog.csdn.net/u012813201/article/details/75007735
(1)写一个算法,不用任何额外变量交换两个整数的值
a=a^b
b=a^b
a=a^b
————————————————————————————————————-
(2)非比较法,判断大小
对于两个32位整数a和b,请设计一个算法返回a和b中较大的。但是不能用任何比较判断。若两数相同,返回任意一个。给定两个整数a和b,请返回较大的数。
首先对数n右移31位,再&1获得符号位,判断c=a-b的符号位即可。
注意当a为负b为正时,a-b可能产生溢出。
public class Compare {
public int getMax1(int a,int b){//当a为负 b为正时,a-b可能会产生溢出,高位的符号位错误,所以getMax方法更安全。
int c=a-b;
int returnA=sign(c);//获取想减结果的符号位
int returnB=flip(returnA);
return a*returnA+b*returnB;
}
public int getMax(int a, int b) {
int c=a-b;
int sa=sign(a);
int sb=sign(b);
int sc=sign(c);//获取想减结果的符号位
int difSab=sa^sb;//a b不同号 0---同号 1---不同号
int sameSab=flip(difSab);//a b同号: 0--不同号 1--同号
int returnA=difSab*sa+sameSab*sc;//如果ab不同号:returnA=sa,sameSab=0,不会用到sc
int returnB=flip(returnA);//如果ab同号:sameSab=1,会用到sc。这里因为ab同号所以其想减后不会溢出。
return a*returnA+b*returnB;
}
public int sign(int n){//返回0--负数 1---非负
return flip((n >> 31) & 1);//带符号位右移31位,&1是获取符号位
}
public int flip(int n){
return n^1;
}
}
————————————————————————————————————-
(3)
寻找奇数出现:时间
O(n),
空间
O(1)
有一个整型数组A,其中只有一个数出现了奇数次,其他的数都出现了偶数次,请打印这个数。要求时间复杂度为O(N),额外空间复杂度为O(1)。给定整形数组A及它的大小n,请返回题目所求数字
思路:因t^t=0,t^0=t;且异或满足交换律和结合律。所以int e=0,依次e^a[i]异或,最后结果,即为出现奇数次的数。
public class OddAppearance {
public int findOdd(int[] a, int n) {
// write code here
int e=0;
for(int i=0;i<n;i++){
e=e^a[i];
}
return e;
}
}
————————————————————————————————————-
(4)两个奇数次的数:
给定一个整型数组arr,其中有两个数出现了奇数次,其他的数都出现了偶数次,找到这两个数。要求时间复杂度为O(N),额外空间复杂度为O(1)。
给定一个整形数组arr及它的大小n,请返回一个数组,其中两个元素为两个出现了奇数次的元素,请将他们按从小到大排列
思路:首先和(4)题一样,e=e^a[i]最终得到e=m^n(假定m n是出现奇数次的两个数),那么e–>二进制,肯定存在值为1的位置,假定第k位的值为1,说明m n在第k位上不同。
假定m的第k位为1,n的第k位为0。e2=e2^x;x是数组中第k位为1的所有数,那么最终e2=m。而n=e^e2
public class OddAppearance {
public int[] findOdds(int[] arr, int n) {
int e1=0;
for(int i=0;i<n;i++){
e1=e1^a[i];
}
int rightOne=e1&(~e1+1);//从右数 e1中第一个值为1的位置。**************第k位
int e2=0;
for(int cur:arr){
if((cur&rightOne)==1){
e2=e2^cur;
}
}
int m=e2;
int n=e2^e1;
int small=Math.min(m,n);
int large=Math.max(m,n);
return new int[]{small,large};
}
}