面试题收集(持续更新~)
作者:互联网
1、关于位运算的使用
(题目一)、在一个数组中,有一个数出现了奇数次,其他数都出现了偶数次,请问怎么知道出现奇数次的数是什么,要求时间复杂度是O( N ) ,空间复杂度是 O( 1 )。
(题目二)、在一个数组中,有两个数出现了奇数次,其他数都出现了偶数次,请问怎么知道出现奇数次的两个数分别是什么,要求时间复杂度是O( N ) ,空间复杂度是 O( 1 )。
提示:异或运算,异或运算支持 交换律、结合律
题目一解答:创建一个成员变量eor为 0 ,将数组遍历一次,每个元素都与成员变量进行异或运算,出现偶数次的数都会被消除,所以最后成员变量的值就是出现奇数次的那个数了;
题目二解答:首先还是创建一个成员变量eor1为0,将数组遍历一次,每个元素都与成员变量进行异或运算,出现偶数次的数都会被消除,所以最后成员变量的值就是出现奇数次的那两个数的异或值了,eor1为两个数的异或值。因为两个数不相等,所以异或结果一定不为0;从二进制的角度看就是这两个数的二进制数至少有一位是不相同的,这就是这道题的突破口。我们可以再创建一个成员变量eor1为0,找出所以那一位是 0 或者 1 的数,再和成员变量eor2进行异或,那么得到的结果一定是这两个数中的其中一个,最后拿这个数与eor1进行异或运算就可以得到另外一个数了;
以下是这两道题的代码:
public class EvenTimeAddTime {
public static void main(String[] args) {
int[] arr1 = {3, 3, 5, 5, 2, 2, 2, 2, 7, 1, 1};
int [] arr2 = new int[]{3,3,5,5,5,2,2,2,2,7,1,1};
process1(arr1);
process2(arr2);
}
//题目一
public static void process1(int[] arr) {
int eor = 0;
for (int i : arr) {
eor ^= i;
}
System.out.println("---------题目一----------");
System.out.println(eor);
}
//题目二
public static void process2(int[] arr) {
int eor1 = 0;
for (int i : arr) {
//两个出现奇数次的元素的异或值
eor1 ^= i;
}
//提取出eor1二进制中最右边的1
int rightOne = eor1 & (~eor1 + 1);
int eor2 = 0;
for (int j : arr) {
//筛选出与rightOne二进制为1对应位不同的数进行异或,就可以得到一个奇数次的数了
if ((rightOne & j) == 0) {
eor2 ^= j;
}
}
System.out.println("---------题目二----------");
System.out.println("一个出现奇数次的数:" + eor2);
System.out.println("另一个出现奇数次的数:" + (eor2 ^ eor1));
}
}
标签:eor2,面试题,eor1,题目,收集,int,更新,异或,数次 来源: https://blog.csdn.net/qq_45331617/article/details/120586639