题目
一个整型数组 nums 里除两个数字之外,其他数字都出现了两次。请写程序找出这两个只出现一次的数字。要求时间复杂度是O(n),空间复杂度是O(1)。
简化版
首先研究一下简化问题:一个数组中只有一个数字是出现一次,其他所有数字都出现了两次。
方法一:
通过排序和两个指针来判断
这个方法时间复杂度和空间复杂度都很高
void bubbleSort(int arr[], int size) {
//顺序
for (int a = 0; a < size - 1; a++){
//最多size-1轮比较
for (int b = 0; b < size - 1 - a; b++){
if (arr[b]>arr[b + 1]){
int c = arr[b];
arr[b] = arr[b + 1];
arr[b + 1] = c;
}
}
}
}
int findlone(int* arr1,int size){
assert(arr1);
bubbleSort(arr1, size);
int *one = arr1;
int* two = arr1 + 1;
while (two){
if (*one == *two){
one += 2;
two += 2;
}
else{
return *one;
}
}
return 0;
}
方法二(最优):
使用异或
int findlonely(int *arr, int size){
int a = 0;
for (int i = 0; i < size; ++i){
a = a^arr[i];
}
return a;
}
方法三:
计数法
int find3(int* arr, int size){
int num = 0;
for (int i = 0; i < size; i++){
num = 0;
for (int j = 0; j < size; j++){
if (arr[i] == arr[j]){
num++;
}
}
if (num == 1){
return arr[i];
}
}
return ;
}
完整解法
思路:
1.将所有元素异或求解;
2.找出解二进制最低位置的1(只要找个1分开两个数字就可以);
3.在位移运算异或求解。
int sumeor(int *arr, int size){
int a = 0;
for (int i = 0; i < size; ++i){
a = a^arr[i];
}
return a;
}
int finddifferentX(int num){
int count = 0;
while (count < 32 && (num & 1) == 0){
num = num >> 1;
count++;
}
return count;
}
void findtwosingle(int *arr, int size){
if (size < 2){
return;
}
int count = 0;
count = finddifferentX(sumeor(arr, size));
int num1 = 0;
int num2 = 0;
for (int i = 0; i < size; i++){
//arr[i] = arr[i] >> count;
if (((arr[i] >> count)&1) == 0){
num1 = num1^arr[i];
}
else{
num2 = num2^arr[i];
}
}
printf("%d %d", num1, num2);
}