您的位置:首页 > 编程语言 > C语言/C++

C语言中的找特殊数字问题

2016-04-19 14:49 393 查看
在C语言的学习过程中,你一定遇到过如何在一个数组中找到一个特殊的数字,这个数字只出现一次,而其他数字都是成对出现的,请你找出这个特殊的数字。如果你是第一次遇到这个问题,那么可能你不能一下子想到最好的方法,当然也有可能你思维特别敏捷,一下子就可以想到最好的解决方法——异或,把这一串数字从头到尾异或,最终得到的那个数字就是你要找的数字。

附上代码:

#include<stdio.h>
#include<stdlib.h>
int main()
{
int N = 0, Special_Num = 0, i = 0;
int * Pnum = NULL;
printf("请输入您要测试的数据的个数:\n");
scanf("%d", &N);
Pnum = (int *)malloc(sizeof(int)* N);
printf("请依次输入您要测试的数据:\n");
for (size_t i = 0; i < N; i++)
{
scanf("%d", Pnum + i);
Special_Num ^= *(Pnum + i);                     //从头到尾异或
}
printf("这个特殊的数字是:%d\n", Special_Num);
return 0;
}
那么如果将问题改下,改成在一个数组,或者在一堆数字之中找到两个特殊的数字,只有这两个数字出现一次,其他的数字都是成对出现,让你找出这两个数字,可以说这道题目与上面的题目很类似,那么一种数学思想就可以运用了,那就是分解思想,将一个问题分成你所遇到过的问题,比如既然这个数组之中有两个数字不同,那么你是不是可以将这两个数字分开来寻找,进一步思考 ,既然可以分开来寻找,那么可不可以将这个数组分成两个子数组,使得每个子数组中都只有一个唯一的元素以及很多成对的元素,那么我们就可以求出每个子数组中唯一的元素,最终就可以得到原数组中2个出现次数唯一的元素。

具体的方法如下:

1. 首先数组中所有元素依次异或,因为相同的元素异或得到0,所以最终的答案就等于那2个唯一的元素a^b的值。

2. 因为a,b不同,所以异或得到的答案肯定是不等于0的,那么我们就找到a^b的二进制表示中第一个为1的位,假如是第k位。而a,b两个数在第k位上是不同的,一个为0,一个为1

3. 接下来我们将第k位是1的分成一组,第k位是0的分成一组,如果2个元素相同,那么他们第k位肯定是一样的,所以肯定被分到同一组中。而a,b则被分到2组中去了。

然后我们就可以在每个分组中异或每一个元素,最终就可以得到那2个唯一的元素

附上测试的代码:

#include<stdio.h>
#include<stdlib.h>
int main()
{
int N = 0, i = 0;
int * Pnum = NULL;
int num1 = 0;
int num2 = 0;
int k = 1, j = 0;
int end_num = 0;                          //测试用的数字
int flag = 0;
printf("请输入您要判别的数字的个数\n");
scanf("%d", &N);
Pnum = (int *)malloc(sizeof(int)*N);
printf("请依次输入内容:\n");
for (int i = 0; i < N; i++)
{
scanf("%d",Pnum + i);
}
for (int i = 0; i < N; i++)
{
end_num ^= *(Pnum + i);           //从头到尾异或
}
while (!(end_num & 1))                    //从最低位开始找,找到一个为1的数字,并记录位数
{
flag++;
end_num >>= 1;
}
for (int i = 0; i < N; i++)
{
int tmp = Pnum[i] >> flag;        //根据这个位数将数组分为两组,两个数字被分在不同的组
if (tmp & 1)
{
num1 ^= Pnum[i];
}
else
{
num2 ^= Pnum[i];
}
}
printf("您要找的数字为:%d  %d", num1, num2);
return 0;
}
其实很多问题都可以完成从复杂到简单的转化,有时候知识我们没想到怎么转化而已。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: