1.2 如何找出唯一成对的数(4种解法)

Posted kaml8

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了1.2 如何找出唯一成对的数(4种解法)相关的知识,希望对你有一定的参考价值。

作者:acDream_ 
来源:CSDN 
原文:https://blog.csdn.net/acDream_/column/info/32487

原文是用Java实现的,自己理解后用C语言实现,记录下来。

 

Problem:
1-1000这1000个数放在含有1001个元素的数组中,只有唯一的一个元素值重复,其他均只出现一次。设计一个算法,将它找出来,你能否设计一个算法实现?

思路1(最先想到的):

首先也是最暴力的方法就是一个循环嵌套一个循环,一个一个去找

时间复杂度为O(n²)

下面是实现的代码:

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int a[11]={1,2,3,4,4,5,6,7,8,9};
 6     int i,j;
 7     int size=sizeof(a)/sizeof(a[0]);           //sizeof(a)得到的是 整型长度4*元素个数
 8     for(i=0;i<size;i++)
 9         for(j=i+1;j<size;j++)
10             if(a[i]==a[j])
11                 printf("%d
",a[i]);
12 
13     return 0;
14 }

思路2:

另外开辟一个大小为1001的数组arr,遍历原来的数组,原来数组中的数就是arr中的下标,若遇到一个数就将对应arr的下标位置对应的值加一就行。然后遍历arr数组,若遇到下标位置对应的值为2的时候,输出下标就行

时间复杂度为O(n)

下面是实现的代码:

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int i;
 6     int a[11]={1,2,3,4,4,5,6,7,8,9};
 7     int b[11]={0};
 8     int size=sizeof(a)/sizeof(a[0]);
 9     for(i=0;i<size;i++)
10     {
11         b[a[i]]++;
12         
13         if(b[i]==2)
14         printf("%d
",i);
15     }
16     return 0;
17 }

思路3:

使用异或来找出唯一成对的数,这种算法的效率应该是最高的了,而且不需要辅助空间

先来说一下异或的规则:

a^a=0

a^0=a

然后我们的思路是将这1001个数全部异或起来,那么就会把相同的数给变成0了,那么怎么办呢?

我们可以再次将该数与1-1000之间的数给异或起来

那么不重复的数都会变成0,而重复的数不会变成0

时间复杂度为O(n)

下面是实现的代码:

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int i,s1=0,s2=0;
 6     int a[11]={1,2,3,4,4,5,6,7,8,9};
 7     int size=sizeof(a)/sizeof(a[0]);//size=11
 8     for(i=0;i<size;i++)
 9         s1=s1^a[i];//s=5
10     for(i=1;i<size-1;i++)
11         s2=s2^i;
12         
13     printf("%d
",s1^s2);
14 
15     return 0;
16 }

s1=(1000个数^)  ^  重复数

s2=1000个数^ 

s1^s2=(1000个数^)   ^  重复数   ^   (1000个数^)   =   0  ^  重复数  =  重复数

思路4:

数学求和法,因为只有一个数字重复一次,而数又是连续的,根据累加和原理,对数组的所有项求和,然后减去1至N-1的和,即为所求的重复数。

时间复杂度为O(n)。
下面是实现的代码:

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int i,s1=0,s2=0;
 6     int a[11]={1,2,3,4,4,5,6,7,8,9};
 7     int size=sizeof(a)/sizeof(a[0]);//size=11
 8     for(i=0;i<size;i++)
 9         s1=s1+a[i];
10     for(i=1;i<size-1;i++)
11         s2=s2+i;
12         
13     printf("%d
",s1-s2);
14 
15     return 0;
16 }

1.3 找出落单的数,这样编程就对了

Problem:

一个数组里除了某一个数字外,其他的数字都出现了两次。请写程序找出这个只出现一次的数字。

Hint: 

这个问题比上一个问题(如何找出唯一成对的数)简单多了,这里直接异或就行了

实现代码:

 1 #include<stdio.h>
 2 
 3 int main()
 4 {
 5     int i,s=0;
 6     int a[11]={1,1,2,3,4,2,3,4,5,6,5};
 7     int size=sizeof(a)/sizeof(a[0]);//size=11
 8     for(i=0;i<size;i++)
 9         s=s^a[i];
10         
11     printf("%d
",s);
12 
13     return 0;
14 }

 

以上是关于1.2 如何找出唯一成对的数(4种解法)的主要内容,如果未能解决你的问题,请参考以下文章

1.2找数组中唯一成对的那个数

位运算-查找数组中唯一成对的数

算法很美Java版

找出数组中不是成对出现的数字

位运算

3位反序数