好久没写博客了,说明我好久没有努力了。好惭愧。
题目:一个整型数组里除了两个数之外,其他数都出现了两次。找出这两个出现一次的数。
一、第一个想法是借助辅助数组以及折半插入来实现。(原数组为vector<int >data)
思路:
1、创建两个数组一个大小均为 (data.size()-2)/2+2。也就是不包含重复数字的总个数。两个数组分别为
int arr[]用于存储数字,和int temp[] 用于记录是否重复。arr[0] = data[0],temp[0] = 0。
2、遍历原数组vector<int >data。通过折半插入放入数组int arr[]中。
3、在折半插入过程中,如果要插入的数在arr[]数组中已经存在,循环continue,同时把对用temp[i]设为-1,
表示arr[i]这个数出现过两次。如果插入的数在arr[]数组中不存在,则arr[]数组与temp[]数组同时执行后移。
4、之后再通过遍历temp[]数组,将 temp[i] != -1 对应arr[i]中的值分别赋值给num1,num2即可。整个过程
时间复杂度为O(N*logN)
代码:
//折半查找
int binarySeek(int *a,int begin,int end,int num,int *temp){
int mid= begin+(begin+end)/2;
while(begin<=end)
{
mid = begin+(end-begin)/2;
if(a[mid]<num)
begin = mid+1;
else if(a[mid]>num)
end = mid-1;
else if(a[mid] == num)
{
temp[mid] = -1;
return -1;
}
}
return begin;
}
//插入排序
void insertSort(int *arr,vector<int> data,int *temp,int *num1,int *num2){
int j=0;
//遍历data数组
for(int i=1;i<data.size();i++)
{
int num = data[i];
int begin = 0;
int end = j;
//折半查找
int set = binarySeek(arr,begin,end,num,temp);
//待插入的值为重复值
if(set == -1)
continue;
//待插入的值为新值,arr 与 temp 都要后移
else
{
j++;
int k = j;
while(k>set)
{
arr[k] = arr[k-1];
temp[k] = temp[k-1];
k--;
}
arr[k] = num;
temp[k] = 0;
}
}
int m = 0;
//遍历temp 寻找需求值
for(int i=0;i<=j;i++)
{
if(temp[i]==0)
{
int a = arr[i];
if(m ==0)
{*num1 = a;m++;}
else
*num2 = a;
}
}
}
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
if(data.empty()||data.size()<2)
return ;
int arrLength = (data.size()-2)/2+2;
int *arr = new int[arrLength];
int *temp = new int[arrLength];
arr[0] = data[0];
temp[0] = 0;
//插入排序
insertSort(arr,data,temp,num1,num2);
}
二、第二个想法是通过 异或运算 实现 原数组为 vector<int >data
思路:
1、既然数组中除了两个不同的数出现一次之外,其他的数都出现过两次。则除了这两个数之外,
其他所有数经过异或运算得出的值为0。因此整个vector<int >data数组得到的异或值,就是所要求
的两个数的异或值。
2、由于这两个数不同,异或值一定不为0,在二进制表示中异或值必有一位(设第i位)为1,这个1,
意味两个数中一个数的第i位为0,另一个数的第i位为1。因此可以通过第i位为是否为1 把原数组data
分为两个数组,一个数组中所有数第i位为0,另一个数组中所有数第i位为1.
3、分别对两个数组进行异或运算,得到的两个值即所需要求的两个值。
时间复杂度为O(N)
代码:
//得到第i位作为分隔数组的条件
int getPosition(int xorNum){
int position = 0;
while((xorNum&1)==0&&position<32)
{
xorNum = xorNum>>1;
++position;
}
return position;
}
//判断第i为是否为1
bool judge(int num,int position){
num = num>>position;
return (num&1)==1;
}
void FindNumsAppearOnce(vector<int> data,int* num1,int *num2) {
int a,b;
a=b=0;
if(data.empty()||data.size()<2)
return ;
int xorNum = 0;
for(int i=0;i<data.size();i++)
xorNum^=data[i];
int position = getPosition(xorNum);
for(int i=0;i<data.size();i++)
{
if(judge(data[i],position))
a^=data[i];
else
b^=data[i];
}
*num1 = a;
*num2 = b;
}