大家刷题的时候是否遇到过这样一个题:
题目描述:在一个二维数组中存在两个不同的元素,你能找出他们吗?
题目解答:
我们先自己设定一个数组,一维二维都可以
假设我设定一个二维数组:
int[][] arr4 = {{1,2,3,4,5},{1,2,3,4,5,203,105}};
我们可以看出两个不同的元素是:203 105
那么此时我们该如何找出这两个不同的元素呢?
对咯!我们可以使用我们的异或操作符(^):二进制位上如果数值不同就是1,如果数值相同就是0
相等的两个数异或之后就等于0
例如:
3 0000 0011
^
3 0000 0011
--------------------
0 0000 0000
得到的数值竟然是0,我们可以想到,要是将二维数组中的每一个数都进行疑惑操作我们是不是就可以找出不同的数了呢?不对,我们要有两位不相同的元素,怎么办呢?
两个不同的元素进行异或操作(^)
2 0000 0010
6 0000 0110
-------------------
4 0000 0100
聪明的你一定发现了,其中异或完了之后的有1的位数,其实他两个二进制位是不一样的,是不是此时我就找到了他们不同的点了呢?
其中必定有一个数在此位置的二进制位是1,另一个是0。
那我们就顺藤摸瓜,找到这两个数吧!
代码及注释如下:
int ret = 0; //设定一个初始值:0和任何数异或(^)都等于任何数
for (int i = 0; i < arr4.length ; i++) {
for (int j = 0; j < arr4[i].length ; j++) {
ret ^= arr4[i][j]; //将二维数组的每一个元素都进行异或,得出最后那个数
//得出的这个数就是不同的两个元素异或出来的结果
}
}
那么已经找到了不同的两个元素异或的结果了,那么接下来进行二进制位的剥离
int pos = 0; //定位器,定位二进制位数哪个地方有1
for (int i = 0; i < 32 ; i++) {
if(((ret>>i) & 1) == 0) //将最终的数进行向右偏移的操作,知道把二进制所有的数进行遍历完毕
{ //一旦遇到0,我们就继续向右移动,直到遇见了1,我们的pos就停止,记录位置
pos++;
break; //只要遇见了1,该循环就没有意义了,因为不同点已经找到了,跳出循环
}
}
// 此时得到pos的数值 ,我们就知道ret的二进制位哪里有1,哪里有不同之处
已经知道哪里有不同之处,我们就应该去寻找这个数,我们先定义两个数准备存储,这两个数随便设置,他只是一个接收器。
int numx = 0;
int numy = 0;
上文说到,任何数和0去进行异或(^)操作都会得到任何数,相同的数进行异或就会得到0
既然是这样,数组中恰好有两个不同的数,其余的都是相同的
我们把不同之处的位数进行区分,异或结果是1的和num1去进行异或,得出一个元素,再将异或结果是0的放置在一个元素中,得到最后一个不同的元素
那么其余的数进行异或(^)操作是不是就得到的是0,那我们是不是就完美的把我们需要找的两个元素都存放在这两个接收器里面了呢?
for (int i = 0; i < arr4.length; i++) {
for (int j = 0; j < arr4[i].length ; j++) {
if(((arr4[i][j] >> pos) & 1) == 1) //进行所有元素遍历,将pos位为1的放在numx中
{
numx ^= arr4[i][j];
}
else if (((arr4[i][j] >> pos) & 1) == 0) { //进行所有元素遍历,将pos位为0的放在numy中
numy ^= arr4[i][j];
}
}
那此时是不是就完美的将两个不同的数进行剥离了呢?我们看结果:
原数组中的不同的两个元素是103和205
编译结果:
已经解决问题了?今天你学废了吗?
别急,我们再来看看,为什么不同的元素一旦设置大了之后就会出现这种情况呢?
之后我会在评论区将解答方式发出来,大家集思广益,请大佬在评论区多多指教!谢谢
码字不易,给个关注吧!后面我将持续更新有关于Java / C / C++有关的知识点和大家交流!
全部代码如下:
int[][] arr4 = {{1,2,3,4,5},{1,2,3,4,5,203,105}};
int ret = 0;
for (int i = 0; i < arr4.length ; i++) {
for (int j = 0; j < arr4[i].length ; j++) {
ret ^= arr4[i][j];
}
}
// 此时得到ret的数值 接下来就要进行剥离
int pos = 0;
for (int i = 0; i < 32 ; i++) {
if(((ret>>i) & 1) == 0 )
{
pos++;
break;
}
}
// 此时得到pos的数值 ,我们就知道哪里有1
int numx = 0;
int numy = 0;
for (int i = 0; i < arr4.length; i++) {
for (int j = 0; j < arr4[i].length ; j++) {
if(((arr4[i][j] >> pos) & 1) == 1)
{
numx ^= arr4[i][j];
} else if (((arr4[i][j] >> pos) & 1) == 0) {
numy ^= arr4[i][j];
}
}
}
System.out.println(numx + " " + numy);
}