Chinaunix首页 | 论坛 | 博客
  • 博客访问: 43689
  • 博文数量: 15
  • 博客积分: 0
  • 博客等级: 民兵
  • 技术积分: 176
  • 用 户 组: 普通用户
  • 注册时间: 2014-01-31 01:57
个人简介

资深码农

文章分类

全部博文(15)

文章存档

2016年(3)

2014年(12)

我的朋友

分类: C/C++

2014-02-08 13:02:45

给定一个成员都大于0的int型数组,里面除了有一个单独的数以外其他的数都是成对出现的,而且这个数组中数的排列是随机的没有任何顺序的,比如it theArray = { 3, 7, 13, 16, 7, 13, 16}; 要求用最快的速度找出这个落单的数。
听上去问题并不难,我们的第一个想法是对数组进行一个二重循环,找出这个落单的数,代码如下

点击(此处)折叠或打开

  1. int findSingleV1(int theArray[], int size) {
  2.     int i, j;
  3.     for (i = 0; i < size - 1; i++) {
  4.         for (j = i + 1; j < size; j++) {
  5.             if (theArray[i] == theArray[j])
  6.                 break;
  7.         }
  8.         if (j == size)
  9.             return theArray[i];
  10.     }
  11.     return 0;
  12. }
成功的话返回这个数,失败的话返回0(给定数组中的数都大于0)。
就到此为止了吗?没有,V1的查找的时间复杂度为n的平方,显然不是最好的解决方案。下面我们可以考虑用排序来对数组进行处理,然后再找出单独的数,代码如下,

点击(此处)折叠或打开

  1. int myCompare(const void *a, const void *b) {
  2.     return (*(int *)a > *(int *)b) ? 1 : -1;
  3. }

  4. int findSingleV2(int theArray[], int size) {
  5.     int i;
  6.     qsort(theArray, size, sizeof(theArray[0]), myCompare);

  7.     // find single number
  8.     for (i = 0; i < size - 1;) {
  9.         if (theArray[i] == theArray[i+1]) {
  10.             i += 2;
  11.             continue;
  12.         }
  13.         return theArray[i];
  14.     }
  15.     if (i == size - 1 )
  16.         return theArray[i];
  17.     return 0;
  18. }
V2中我们用到了C标准库中的qsort,因此需要自己单独定义一个compare函数。代码也比较简单,采用排序先进行处理以后,算法复杂度为NLogN。
下面我们看一个使用线性时间就可以找出答案的最快算法,

点击(此处)折叠或打开

  1. int findSingleV3(int theArray[], int size) {
  2.     int i = 0, temp;
  3.     while (i < size) {
  4.         temp ^= theArray[i++];
  5.     }
  6.     return temp;
  7. }
这个算法使用了平时并不常用的异或运算符,利用了异或运算符的如下性质,
输入
运算符
输入
结果
1
^
0
1
1
^
1
0
0
^
0
0
0
^
1
1
异或运算的特点是:两个相同的位异或得0,不同的位异或得1,不论是0还是1只要与0进行异或得出的结果都不变。这样的话在一个数组中如果很多对数字成对出现,那么他们按位异或的结果仍然为0,而这个0和那个单独出现的数再进行异或,得到的数就是这个落单的数的值,这个算法最为快速,也最为巧妙。






阅读(1654) | 评论(0) | 转发(0) |
给主人留下些什么吧!~~