杀死那个单身狗 --< ^按位异或操作 >

      话说在那狗星上,生活着一群情侣狗和单身狗,但单身狗的比例太高,让狗星管理员紫薯精发了愁,聪明的狗管理紫薯精 灵光一闪  “我只要消灭所有的单身狗,单身比例不就能下来了吗^ _ ^”,于是他带上手套,打了个响指,可是,怎么能在狗群里找到单身狗呢?

       任给一个2N+1个无序元素,其中N对为成双数字,一个为成单数字X,求出x的值;

例如:arr[9]=  { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 }   则成单数字为1。

        不难想到,可以通过不断遍历来寻找相同的数字,以上为例:首先保存z=arr[0];不断的向后遍历是否找到arr[y]=x,若无则z=arr[1],继续重复,直到找到X。

 代码示例: 

#include<stdio.h>
int main()
{
	int arr[9] = { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 };
	for (int i = 0; i < 9; i++)
	{
		int flag = 1;                              //用flag来记录是否出现重复数字,出现后flag置0
		int x = *(arr + i);
		for (int j = 0; j < 9; j++)
		{
			if (i == j)                  //当遍历到其本身时,用continue来跳过其本身
				continue;
			else  if (x == *(arr + j))
				flag = 0;
		}
		if (flag)
			printf("%d\n", x);
	}
}

         但不难发现,其时间复杂度O(n^2),狗管理对这杀狗效率非常不满,为了更高效的猎杀单身狗,我们今天将要引入一个操作符     ^  (按位异或)

         ^      c语言相较于其他语言,其有一特点是允许执行位操作,众所周知,计算机中任何数据都是转换为二进制储存。以int类型的3和5为例,转换为二进制后,异或操作为  比较相同每一位,均为1或0则得1,不同则为1;

       

转换为十进制为   3^5 = 6;

由此我们易推出

1.  任何数异或其本身都为0

2   0 异或任何数X都为X

3.  (a^b)^c==a^(b^c)              

      基于以上考虑,可得任何对成双数字异或后得到均为0;且0异或一个成单数字得其本身;

so  这为我们更好的找到单身狗提供了思路:只需将所有数字全部异或便得到成单数字;

#include<stdio.h>
int main()
{
	int arr[9] = { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 };
	int x = 0;
	for (int i = 0; i < 9; i++)
	{
		x = x ^ *(arr + i);
	}
	printf("%d", x);
}

 这时代码更加简洁,且时间复杂度为O(n),紫薯精开心的笑了;

  ONE  MORE  

             当再加入一只单身狗时,还能将他们找出吗?

例;arr[10]= { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 ,  8}     (现有成单数字8,1)

由上可知,如果我们还是将他们全部异或时,得到的X=8^1   

不妨设成单数字为  D S ,,则我们可以得到一个X=D^S;

但仅仅是一个X,我们是可以将其分为许多组解,而其中仅有D S是满足题意的

所以,我们就会想,是否可以将D S分成两组进行异或,由于D!=S,则X=D^S必有某位为1,则D 和 S 在该位上必有一个是0,一个是1,所以我们可以依照是否某位上为1或0将数组分为两组分别求异或;

还是以  arr[10]= { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 ,  8}为例;1^8其中第1和第4位为1,则我们可以将他们按照第1位是否为1(这时候就相当于分奇偶)

 代码如下:

 更更更进一步:

       当有n只单身狗时,是否能找出他们呢?

思考:   仿照上面的思想,第一遍全体异或时,我们可以得到

X=n_1 ^ n_2 ^ n_3......n_n-1 ^ n_n;  的数,再以某一位是否为1将全体分为两组,再两组分别异或,

每组再分成两组,重复操作直到每组仅有一个成单数字时结束.

但,反思后发现,由于我们并不知道具体的数字是什么,每次分组时无论是成双数字还是成单数字,

可以说是随机分配的,没有一个指标能够显示出组内仅有一个成单数字,

比如  共有4只单身狗,第一次分组时,他有可能是分成2+2,也有可能是1+3 (且每组的数字个数也是随机的,不一定相等),所以目前还未想出依据什么来判断是否仅有一只单身狗----未完待续??

✿ヽ(°▽°)ノ✿
 

关于异或的其他操作

1 .异或操作可以让我们不借助中间变量来实现两数交换

例如  a=1,b=2,   交换后  a=2,b=1;

{         a=a^b;

          b=a^b;

          a=a^b;
}

(其实加法也可以实现   a=a+b;   b=a-b;   a=a-b;)

        

找两只单身狗的代码段

#include<stdio.h>
int main()
{
	int arr[10] = { 2, 4, 3 ,5 ,5, 4, 2, 1, 3 ,8};
	int x = 0;
	for (int i = 0; i < 10; i++)
	{
		x = x ^ *(arr + i);
	}
	int y = 1;
	while (x % 2 == 0)                  //找到第几位是1,用y记录。
	{
		y++;
		x = x >> 1;
	}
	int D = 0;
	int S = 0;
	for (int i = 0; i < 10; i++)
	{
		if ((*(arr + i) >> (y - 1)) % 2 == 1)          //以第几位是否为1来将所有元素分为两组;
		{
			D = D ^ *(arr + i);
		}
		else
		{
			S = S ^ *(arr + i);
		}
	}
	printf("%d  %d", D, S);
}
评论 3
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值