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\n",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\n",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\n",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\n",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\n",s);
12
13     return 0;
14 }

原文地址:https://www.cnblogs.com/kaml8/p/10356179.html

时间: 2024-10-24 22:09:11

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

C++实现 找出10000以内的完数

C++实现 找出10000以内的完数 #include <stdio.h> int main(){ int n; // 用户输入的整数 int i; // 循环标志 printf("输入一个整数:"); scanf("%d",&n); printf("%d=",n); // n>=2才执行下面的循环 for(i=2; i<=n; i++){ while(n!=i){ if(n%i==0){ printf("

找出第k大的数

编程题#3:找出第k大的数 来源: POJ (Coursera声明:在POJ上完成的习题将不会计入Coursera的最后成绩.) 注意: 总时间限制: 1000ms 内存限制: 65536kB 描述 用户输入N和K,然后接着输入N个正整数(无序的),程序在不对N个整数排序的情况下,找出第K大的数.注意,第K大的数意味着从大到小排在第K位的数. 输入 N K a1 a2 a3 a4 ..... aN 输出 b 样例输入 5 2 32 3 12 5 89 样例输出 32 提示 这是一道很经典的算法问

笔试题--在一个整数数组中找出第5大的数

/** * 在一个整数数组中找出第5大的数 * 思路是首先在数组中找到最小数,然后依次找到第五大的数 * * @param array * @return */ public static int[] selectionSort(int[] array) { if (array.length == 0) return array; for (int i = 0; i < array.length; i++) { int minIndex = i; for (int j = i; j < arr

找出唯一出现一次的数

1.问题描述:找出数列中唯一一个出现一次的数,其余得数都出现两次. 分析: 1)最笨的方法当然是穷举了: #include <stdio.h> int array[] = { 1 , 3, 3, 1, 5, 5 , 6}; int get_only() { int *ptmp1, *ptmp2; int *arrend = array + sizeof(array) / sizeof(int); for(ptmp1 = array; ptmp1 != arrend; ptmp1 ++) { f

一个有趣的问题,用10只蚂蚁从1000瓶水中找出唯一有毒的一瓶

其实原文说的是10只小鼠,考虑到一些生物伦理问题,小石哥把它换成了10只蚂蚁,可是蚂蚁也是生命.其实不用这么当真的,又不是真的要做这个事. 再具体说一下问题,有1000个装有水的瓶子,其中有一瓶水是有毒的,蚂蚁喝了有毒的水后会在一周的死亡,现在给你10只蚂蚁,和一周的时间,你要从这1000瓶水中找出有毒的那瓶. 作者给出了这样的答案: 把问题简化一下,3只蚂蚁,7个瓶子. 000=0,001=1,010=2,011=3,100=4,101=5,110=6,111=7 把1,3,5,7号瓶子的水给

找出1-N中missing的数

数组a[n-1]里存有1到n的所有数,除了一个数removed,找出这个missing的数. #include <stdio.h> #include <stdlib.h> //数组a[n-1]里存有1到n的所有数,除了一个数removed,找出这个missing的数. //容易发生溢出 时间复杂度O(N),空间复杂度O(1) int missing0(int a[],int n) { int sum=(n+1)*n/2; int i; for(i=0;i<n-1;i++){

算法:找出有序数组中两数,它俩之和等于输入值

题目:已知按序排列的整数数组,输入任意数number,当数组中某两数之和等于number时,打印出两个数. 要求:复杂度为o(n) 解法: 数组已是有序排列,且两个加数一定满足条件:较小加数<= (number/2) <= 较大加数:那么只需要找出该数组的较小加数和较大加数分界index,以该分界为起点分别往左右两边逐个取值匹配. 若两数之和>number,说明较小加数还要再小,向数组的较小值方向移位取值与原较大值重新匹配. 若两数之和<number,说明较大加数还要再大,向数组的

从100万个整数里找出100个最大的数

声明:本文最初发表于<电脑编程技巧与维护>2006年第5期,版本所有,如蒙转载,敬请连此声明一起转载,否则追究侵权责任.网上发表于恋花蝶的博客http://lanphaday.bokee.com 题目:从1亿个整数数中找出最大的1万个. 拿到这道题,马上就会想到的方法是建立一个数组把1亿个数装起来,然后用for循环遍历这个数组,找出最大的1万个数来.原因很简单,因为如果要找出最大的那个数,就是这样解决的:而找最大的1万个数,只是重复1万遍而已. template< class T >

输入一组数,找出满足某条件的数

1.输入一组数,找出它的最大值,最小值,平均值. 关键点是要把第一个数赋值给min,max,sum 1 #include<iostream> 2 using namespace std; 3 int main() 4 { 5 int min,max,sum,i; 6 cin>>i; 7 min = max =sum = i; // 将输入的第一个数赋值,以便后续比较 8 int n = 0; // 统计输入了多少个数 9 while(cin>>i){ 10 n++; 1