在日常的编程中,经常会遇到求一组数据中是否有相同数字的情况,这个问题其实还是相对比较棘手的,我将用一道很经典的题来探讨这个问题。
5位运动员参加了10米台跳水比赛,有人让他们预测比赛结果
A选手说:B第二,我第三;
B选手说:我第二,E第四;
C选手说:我第一,D第二;
D选手说:C最后,我第三;
E选手说:我第四,A第一;
比赛结束后,每位选手都说对了一半,请编程确定比赛的名次。
平常的编程,我们大多数时间是和数据在打交道,忽然蹦上来一道应用题,我想大多数老铁都懵了吧(哈哈,至少我是懵了),但是遇到问题我们要迎难而上,接下来,我们来分析这道题。
(1)首先,五个人参加比赛所以肯定每个人的名次范围是 1~5,那我们先把五名选手的名次进行抽象。
//定义A~B五名选手的名次信息
int a,b,c,d,e;
//使用环罗列出A,B,C,D,E五个人所可能的名次情况
for( a=1; a<=5; a++)
for( b=1;b<=5; b++)
for( c=1; c<=5; c++)
for( d=1; d<=5; d++)
for( e=1; e<=5; e++)
{
//逻辑判断
}
}
}
}
}
(2)罗列出所有的名次情况之后,我们就可以进行逻辑判断了,那么怎么将五位选手的话抽象成程序语言呢,我们在这里可以使用 ‘==’.
//逻辑判断
if( (b==2)+(a==3) ==1 &&
(b==2)+(e==4) ==1 &&
(c==1)+(d==2) ==1 &&
(c==5)+(d==3) ==1 &&
(e==4)+(a==1) ==1 )
{
//输出结果
}
(3)到这里,相信大部分老铁都已经看到了黎明的曙光,立马跟上输出语句
printf("a=%d, b=%d, c=%d, d=%d, e=%d\n",a,b,c,d,e);
如果老铁你就是这么想的那么你会得到这样的结果:
为什么呢,明明都对着呢,怎么会得到这么多的数据。
那老铁你仔细看看,是不是发现这些数据里有一些奇特的东西,每组数据中会有很多的重复数据,所以发生了这样的bug。
有两种解决方案,第一种是在for循环中加入一个标志量,使五次for循环不会产生相同的值,但是想一想就觉得很麻烦,如果下一次的循环是十次,二十次,那代码的长度可想而知。
第二种方法,就是利用bit位的或操作进行判断多个数据中是否有相同的元素,也是今天主要介绍的方法。
判断多个数字中是否有相等的数字
将一组数据分别将1移位,再与一个数字进行或操作,这个数一般选为0,最后判断这个数字的大小是否为预期值即可。
//0在32位平台下的二进制表示为 00000000 00000000 00000000 0000000
int n = 0;
//因为a~e五个数据表示名次,且数值为1~5,所以依次将1移位再与n进行或操作
//n的预期值为 00000000 00000000 00000000 00111110
//转换为十进制为62
n |= (1<<a);
n |= (1<<b);
n |= (1<<c);
n |= (1<<d);
n |= (1<<e);
if(n == 62)
{
printf("a=%d, b=%d, c=%d, d=%d, e=%d\n",a,b,c,d,e);
}
使用这样的方法我们就成功的解决了判断数组中是有相等元素的操作,并且可以应用的很多其他场景中去。
完整代码如下:
#include <stdio.h>
int main()
{
int a,b,c,d,e;
for( a=1; a<=5; a++)
for( b=1; b<=5; b++)
for( c=1; c<=5; c++)
for( d=1; d<=5; d++)
for( e=1; e<=5; e++)
{
if((b==2)+(a==3) ==1 &&
(b==2)+(e==4) ==1 &&
(c==1)+(d==2) ==1 &&
(c==5)+(d==3) ==1 &&
(e==4)+(a==1) ==1)
{
int n = 0;
n |= (1<<a);
n |= (1<<b);
n |= (1<<c);
n |= (1<<d);
n |= (1<<e);
if(n == 62)
printf("a=%d, b=%d, c=%d, d=%d, e=%d\n",a,b,c,d,e);
}
}
return 0;
}
实现环境为CentOS6.5