1、算法描述
给定一个非空数组,除某一个元素出现一次外,其他元素出现两次,找出这个只出现一次的元素并返回。
例如给定[2,2,3,3,4,4,5],则返回值为5;
例如给定[4,4,5,5,-1],则返回值为-1;
例如给定[4,4,5,5,0],则返回值为0;
题解要求:算法具有线性复杂度,并且不适用额外存储空间。
2、算法解析
通过分析题目可知,其他元素都是出现两次,那么针对这出现两次的元素做什么操作可以实现将此元素从数组中剔除的操作呢?答案就是使用我们的按位操作符中的异或(^),即相同bit位异或后为0,不同bit位异或为1,所以我们只需遍历此数组,然后依次将数组中的每一个元素进行异或操作,最终得到的数就是在这个数组中只出现一次的元素。
算法实现:
1 #include <stdio.h>
2
3 int find_the_special_number(int *pArr,unsigned int len)
4 {
5 int temp=0;
6 unsigned int i=0;
7 for(i=0;i<len;i++)
8 {
9 temp^=(*(pArr+i));
10 }
11 return temp;
12 }
13
14 int main(void)
15 {
16 int num[]={2,2,3,3,0};
printf("number is:%d\n",find_the_special_number(num,sizeof(num)/sizeof(int)));
18 return 0;
19 }
3、异或运算符
3.1、参加运算的两个对象,如果两个相应位相同为0,相异为1。
3.2、异或运算的几条常用性质:
1、交换律: a^b =b^a
2、结合律: (a^b)^c == a^(b^c)
3、对于任何数x,都有 x^x=0,x^0=x
4、自反性: a^b^b=a^0=a;
3.3、异或运算的应用
1)翻转指定位
比如将数 X=1010 1110 的低4位进行翻转,只需要另找一个数Y,令Y的低4位为1,其余位为0,即Y=0000 1111,然后将X与Y进行异或运算(X^Y=1010 0001)即可得到。
2)与0相异或值不变
例如:1010 1110 ^ 0000 0000 = 1010 1110
3)交换两个数
void Swap(int &a, int &b){
if (a != b){
a ^= b;
b ^= a;
a ^= b;
}
}
注:负数按补码形式参与位运算。