找出一个数组中的”单身“
来源:互联网 发布:省流量的软件 编辑:程序博客网 时间:2024/05/16 04:57
已知一个数组中,除了一个数字出现一次外,其他数字都出现两次,试找出这个数~~
思路分析:当看到这个题目,我就想,既然只有一个数出现一次,那么我们可以遍历这个数组,只要遇到相同的两
个数,就把它们置为一个比较大的数,最后输出那个没有被改变的数。
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>int main(){int arr[9];int i = 0;int j = 0;for (;i < 9;i++){scanf("%d",&arr[i]);}for (i = 0;i < 8;i++){for (j = i + 1;j < 9;j++){if ((arr[i] == (arr[i] & arr[j]) + ((arr[i] ^ arr[j]) >> 1))){arr[i] = 32767;arr[j] = 32767;}}}for (i = 0;i < 9;i++){if (32767 != arr[i])printf("%d",arr[i]);}system("pause");return 0;}代码分析:
代码缺陷:代码时间复杂度为o(n^2),还有将相同的数分别置成32767,我们不能保证数组中原本就没有 这个 数。
代码亮点:使用了一种比较高端的方法求出两数的平均值,这样就能防止数据过大,两数之和发生溢出。
下边,我来重点解析这种求平均数的妙法~
求平均数的另一种方法:
a和b的平均数mid,mid = (a - b)/2+a;这种方法可以适用于任何类型数的平均数,而上述位运算的方法只能
适用于整形数,且两个数的符号位相同的那种。
学习编程这么久,我们发现,经常一个题目有好多种方法,我们应该择优,也就是,我们的目的不是解决问题,
而是更好的解决问题。上边求平均数的方法中,我们可以发现两个相同的数异或的结果是0,看看我们可否利用
这种方法解决呢??
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>int main(){int arr[] = {1,2,3,4,1,2,5,3,5};int i = 0;int ret = 0;for (i = 0;i < sizeof(arr) / sizeof(arr[0]);i++){ret ^= arr[i];}printf("%d",ret);system("pause");return 0;}上述方法很好的利用了异或运算符,时间复杂度是O(n)。由于代码比较少,所以没有必要写成函数。
如果一个数组中有两个数没有成对出现,其他数都成对,那么我们又是怎样找到这两个数呢??
如果我们能将两个不同的数分开,然后利用上述找一个数的方法也可以找出这两个数。我们将实现方法写成函数的
形式。看以下代码:
#define _CRT_SECURE_NO_WARNINGS 1#include<stdio.h>#include<assert.h>void find_two_num(int arr[], int n, int *p1, int *p2){assert(p1);assert(p2);int i = 0;int ret = 0;//用来存储所有元素异或的结果int pos = 0;for (i = 0;i < n;i++){ret ^= arr[i];}while (((ret >> pos) & 1) != 1){pos++;}for (i = 0;i < n;i++){if (((arr[i] >> pos) &1) == 0){*p1 ^= arr[i];}}*p2 = ret ^ *p1;}int main(){int arr[] = {1,2,3,4,1,2,3,5};int num1 = 0;int num2 = 0;find_two_num(arr,8,&num1,&num2);printf("%d %d",num1,num2);system("pause");return 0;}
在以往的函数中,我们一般只需要一个返回值,而这个程序需要接受两个返回值,怎么办呢??利用返回型参数。
也就是传给函数的是存储数据的地址。
代码解析:我们的目标是将这个数组的元素分开,
比如4,5只出现一次,100^101 = 001,我们根据为1的那一位也就是第0位是否为1将数据分成两组,相同的数必
然被分到一组,不同的数必将位于不同的组,然后将每个组异或就可得到结果~~
我们没有必要将分的组的数保存起来,因为没有必要,只需要将组内的所有元素异或就行。
还有,我们只要求出一个组的单独出现的数,只需要将两个数异或的结果(即为代码中的ret)异或已经求出的
出现一次的数就可以~推导如下:
比如:a ^ b = m;
则: a ^ b ^a = m^a;
b = m ^a;
特别注意:位运算符 的优先级不太高(低于算术运算符的优先级),所以必要的时候不要吝啬括号哦~~
关于位运算符的强大作用,之后我再整理~~以上如有问题,希望大家指出~~
- 找出一个数组中的”单身“
- 找出数组中的“单身狗”
- 找出一个二维数组中的鞍点
- 找出一个数组中不存在于另一个数组中的元素
- 写一个函数,找出一个整数数组中的第二大数
- 找出一个整型数组中的元素的最大值
- 不排序找出一个数组中的第二大的数
- 快速找出一个数组中的最大数、第二大数
- Class 找出一个整形数组中的元素的最大值
- C指针实现找出一个数组中的最大值和次大值
- 快速找出一个数组中的最大数和第二大数
- 快速找出一个数组中的最大数、第二大数。
- 找出数组中的最大值
- 找出数组中的峰值
- 找出数组中下一个大数
- 找出数组中的Single Number
- 找出数组中的主元素
- 找出二维数组中的鞍点
- 通过崩溃trace来查找问题原因
- leetcode——123——Best Time to Buy and Sell Stock III
- 排序与算法
- Compile、Make和Build的区别
- android开发环境搭建
- 找出一个数组中的”单身“
- PHP中new出来的对象和 clone复制出来的对象
- C#中Split用法(把字符串以某个字符为分隔符分成一个数组)
- eclipse svn同步程序报错 Attempted to lock an already-locked dir(使用此方法已经解决问题)
- Codeforces Round #334 (Div. 2) D. Moodular Arithmetic
- SAP ABAP编程 获取物料长文本-其他长文本同理
- org.apache.hadoop.mapred.FileAlreadyExistsException: Output directory hdfs://mycluster/output alread
- JavaSE入门学习34:Java集合框架之Collection接口、子接口及其实现类
- Struts中ActionContext和ServletActionContext的比较 [转]