The single dog and its Plus
众所周知,我们程序猿很多都是社恐或者是喜欢自己一个人的 (别问我为什么知道) ,这样的性格也总是我们吃亏,尤其是在找女朋友这方面(再次申明别问我为什么知道!)
然后的话,来到大学之后几乎每天都要被恋爱的酸臭味给臭死(不过幸好宿舍里没有谈恋爱的,不然........)
那么今天的话我来分享一道有关单身狗的题目,来献给自己,以及屏幕前的你,什么?你有你有女朋友了?hh,感觉给我滚出这篇博客!!!(玩笑而已,各位别当真哈*^v^*~)
那么第一道single dog,题目为:
给定一个整形数组里面放9个元素,‘1’‘2’‘3’‘4’‘5’‘1’‘2’‘3’‘4’ 其中有四对双双成对,但有一个单身狗,请写一段代码找出这个单身狗。
兄弟们有什么思路吗?哈哈,不知道该怎么做吧,那么就睁大你的眼睛看看我的思路!——
上代码!
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
int main()
{
int arr[9] = { 1,2,3,4,5,1,2,3,4 };
int i = 0;
for (int n = 0; n < 9; n++)
{
i ^= arr[n];
}
printf("%d ", i);
return 0;
}
是不是开眼界了?那这个时候请兄弟们回想一下,在你学过位操作符这些之后,你有好好地运用他们吗?是不是几乎没用过呢?那么这一道单身狗问题让你重新对待他们了吗 <(~v~)>
思路其实很简单,铁汁们都可以看得懂,但以防万一博主还是简单讲一下:‘^‘’ 按位异或,二进制中对应的位数相同为0,不同为1。所以两个相同的数字按位异或得到的就是0,0按位异或任何数字得到的是这数字本身,因此只需要遍历数组,将每一项按位异或就可以得到那个单身狗啦!
是不是很简单呢!这其实就是需要打开思维,将自己所学的知识点用上(虽然博主不配这么说)。好了,single dog 做完了,那我们接下来看看single dog plus 吧!
嗯?看我?(~>_<~) 不是看博主啦!
Plus 就是在单身狗的基础上,在一个数组内找两个单身狗哦~ ,元素为‘1’‘2’‘3’‘4’‘1’‘2’‘3’‘4’‘5’‘6’
诶,这时候兄弟们是不是开心了,不就是单身狗多了一个吗,简单!还是按位异或! 嗯?思路不错,但铁汁们有没有想过怎么实现呢?两个单身狗抑或值可是没有意义的哦!
这里博主给出自己一开始的思路:依旧是所有元素抑或,然后遍历数组,因为数组中存在两个元素能够使原所有元素抑或后的值抑或得0,那么不就找到两个单身狗了吗?对不对?没问题吧?是吧? 哈哈,这时就有聪明的好伙伴提出异议了:“不对!一个数组中能使所有元素抑或后的值再抑或得到0的两个数不一定只有一对!”,嗯,没错,博主尝试后发现会有许多组满足条件,代码及结果如下:
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void Finddog(int arr[], int sz)
{
int n = 0;
int x = 1;
for (int i = 0; i < sz; i++)
{
n ^= arr[i];
}
for (int i = 0; i < sz; i++)
{
for (int j = 0; j < i; j++)
{
if (arr[i] ^ arr[j] ^ n == 0)
printf("%d %d ", arr[i], arr[j]);
}
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int num1 = 0;
int num2 = 0;
Finddog(arr, sz, &num1, &num2);
printf("%d %d", num1, num2);
return 0;
}
我们可以看到有很多解,当然我们需要找的单身狗也在里面,那么我们该如何正确的找出这两只呢?
思路难想,但实现简单,这里我直接把思路提供出来:
首先,对数组中的所有数字进行异或运算,结果将是两个只出现一次的数字的异或值。然后,找到这个结果中的任意为1的位,这样两个只出现一次的数字在这个位上是不同的。根据这个位的不同,将数组中的数字分成两组,分别进行异或运算,得到的结果就是这两个只出现一次的数字。
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
void Finddog(int arr[], int sz, int* num1, int* num2)
{
int n = 0;
int x = 1;
for (int i = 0; i < sz; i++)
{
n ^= arr[i];//n为数组中所有元素抑或得到的数字
}
while ((x & n) == 0)
{
x <<= 1;//找出两个单身狗二进制中位数不同的一位
}
*num1 = 0;
*num2 = 0;
for (int j = 0; j < sz; j++)
{
if ((x & arr[j]) == 0)//分组,使得一组中只有一个单身狗
(*num1) ^= arr[j];//然后将每一组抑或,得到的就是单身狗
else
(*num2) ^= arr[j];
}
}
int main()
{
int arr[10] = { 1,2,3,4,5,1,2,3,4,6 };
int sz = sizeof(arr) / sizeof(arr[0]);
int num1 = 0;
int num2 = 0;
Finddog(arr, sz, &num1, &num2);
printf("%d %d", num1, num2);
return 0;
}
铁汁们有没有大开眼界呢?其中比较难想到的就是如何将两个单身狗分开,不给他们结合的机会<(* ̄▽ ̄*)/ 而比较难理解的就是Finddog函数内最后的if函数,这其实也没有什么,我们其实不需要知道那几个值可以使 x & arr[j] == 0 ,因为不管是那些值,除了单身狗外都是成对的,抑或后还是0.
讲到这里兄弟们都懂了吗?作为单身狗总不能做不出单身狗的题目吧?○( ^皿^)っHiahiahia…
通过这道题目,我们要有所收获:
所有学的知识都是有用的,我们不应该轻视每一个知识点,因为说不定哪一道题就会用到它呢? --------不准备秃的大伟
今天太宝贵,不应该为酸苦的忧虑和辛涩的悔恨所销蚀。把下巴抬高,使思想焕发出光彩,像春阳下跳跃的山泉。抓住今天,它不再回来。
那么本篇博客也就到此为止了,送大家一碗鸡汤,勉励自己以及这世界上所有追逐梦想的赤子趁年华尚好努力提升自己,莫欺少年穷!