前言
这种题目直接写得话其实不难,很多同学都能立马想到用循环嵌套的方式来求。但是这种算法终究还是比较矬的(因为当你前面找的那个数已经出现了两次,你已经知道这个数不是单身汉了,可是当外层循环再次走到那个数时还是会进去无效地逐一对比一次,导致了程序运行时间和精简程度一般),并且它的时间复杂度高达O(n^2)不满足有些题目的限制,所以这个方法在这就不多赘述了
只求一个单身汉时
即一个数组里有一个数字只出现了一次,需要你找出来
哈希表遍历法
创建一个长度至少比目标数组数据范围大小大1的哈希数组(要使目标数组每个值都能对应到哈希数组的下标,下标是比数组长度少一位的),然后遍历一遍目标数组,将其与哈希数组下标进行对比,如果相等就使哈希下标对应的数据++(所以一开始要将哈希数组初始化为一个值),之后再遍历一遍哈希数组判断值即可
int main()
{
int arr[7]={1,2,5,3,1,3,2};
int sz=sizeof(arr)/sizeof(arr[0]);
int arr1[6]={0};
for(int i;i<sz;i++)
{
arr1[arr[i]]++;
}
for(int i=0;i<6;i++)
{
if(arr1[i]==1)
{
printf("单身汉为:%d\n",i);
exit(1)
}
}
return 0;
}
这个算法时间复杂度为O(n)明显是好于嵌套循环的
异或
首先了解一下按位异或操作符。异或是针对二进制位操作的操作符,如果二进制位上的数相同则为0,相异则为1 有两个常用性质 1.0异或任何数等于任何数 2.相同的数异或结果为0,且不在乎次序。如:6 ^ 8 ^ 6=6 ^ 6 ^8=8,因为6 ^ 6是等于0的
上代码
int arr[7]={1,2,2,1,5};
int a=0;
int sz = sizeof(arr)/sizeof(arr[0]);
for(int i=0;i<sz;i++)
{
a^=arr[i];
}
printf("%d\n",a);
(进阶)找两个单身汉时
void Search(int* arr,int sz)
{
int a = 0;
int pos = 0;
for (int i = 0; i < sz; i++)
{
a ^= arr[i];
}
int b = a, c = a;
for (int i = 0; i < 32; i++)
{
if ((a >> i) & 1)
pos = i;
}
for (int i = 0; i < sz; i++)
{
if ((arr[i] >> pos) & 1)
b ^= arr[i];
else
c ^= arr[i];
}
printf("%d\n", b);
printf("%d\n", c);
}
int main()
{
int arr[20] = { 1,2,2,3,4,6,6,1 };
int sz = sizeof(arr) / sizeof(arr[0]);
Search(arr,sz);
return 0;
}
好啦好啦讲完了,友友们觉得有用的话可以收藏起来噢
|