你是真的“C”——找单身狗~
Posted 博客小梦
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了你是真的“C”——找单身狗~相关的知识,希望对你有一定的参考价值。
你是真的“C”——找单身狗~😎
😎博客昵称:博客小梦
😊最喜欢的座右铭:全神贯注的上吧!!!
😊作者简介:一名热爱C/C++,算法等技术、喜爱运动、热爱K歌、敢于追梦的小博主!
😘博主小留言:哈喽!😄各位CSDN的uu们,我是你的博客好友小梦,希望我的文章可以给您带来一定的帮助,话不多说,文章推上!欢迎大家在评论区唠嗑指正,觉得好的话别忘了一键三连哦!😘
前言🙌
哈喽各位友友们😊,我今天又学到了很多有趣的知识,现在迫不及待的想和大家分享一下!😘我仅已此文,和大家分享你是真的“C”——找单身狗~ 都是精华内容,可不要错过哟!!!😍😍😍
初阶——找单身狗问题:
在一组数组中,有一只“单身狗”(该数字只出现一次),其他的数字都有一个和自己相同的数字。
其实解答此题有许多的方法,例如直接将数组进行一个排序,然后定义两个指针,然后寻找到单身狗。这里介绍的是用异或运算来解答这道题目,效率也比较高。
异或运算的规律:
- 相同为零,相异为1;
- 任何数和0异或等于其本身
- 两个相同的数异或为0.
解题源码分享: 😘
#include <stdio.h>
int main()
int single_dog[] = 1,2,3,4,1,2,3,4,5 ;
int sz = sizeof(single_dog) / sizeof(int);
int i = 0;
int sin_dog = 0;
for (i = 0; i < sz; i++)
sin_dog^= single_dog[i];
printf("%d", sin_dog);
return 0;
程序输出结果验证: 😊
进阶——找单身狗问题:
在一组数组中,有两只“单身狗”(有两个数字只出现一次),其他的数字都有一个和自己相同的数字。
- 这道题明显比初阶找单身狗的问题难度明显上升,但是解法也很相似。
- 那我们可不可以将这个问题转换成初阶单身狗问题呢?显然是可以的。这道题的核心就是进行一个分组,让两只单身狗分别在不同的组里面。这里举例说明一下两只单身狗为4和5。
- 我们知道 4 的 二进制为:0100 。 5 的二进制为: 0101。可以发现 4 和 5 的最低二进制位上的数字不同。因此,这个可以作为分组的条件。
- 然后依次对每一个组的数字进行一个异或,最终得到每一组的单身狗。
解题源码分享: 😘
#include <stdio.h>
int main()
int single_dog[] = 1,2,3,4,1,2,3,5;
int sz = sizeof(single_dog) / sizeof(int);
int i = 0;
int dog1 = 0;
int dog2 = 0;
for (i = 0; i < sz; i++)
//分组:
// 4 : 0100 5: 0101
if ((single_dog[i] & 1) == 1)
dog1 ^= single_dog[i];
else if((single_dog[i] & 1) == 0)
dog2 ^= single_dog[i];
printf("%d %d", dog1, dog2);
return 0;
程序输出结果验证: 😊
总结撒花💞
本篇文章旨在分享你是真的“C”——找单身狗。希望大家通过阅读此文有所收获😘如果我写的有什么不好之处,请在文章下方给出你宝贵的意见😊。如果觉得我写的好的话请点个赞赞和关注哦~😘😘😘
经典算法题在数组中找两个单身狗
✨前言✨:
算法是一个程序员的内功,能很好的体现程序员的编程思维,通过学习和掌握常见的算法,不仅能提高coding能力,还能更加容易在笔面试中脱颖而出。本专栏将记录博主刷算法题的过程,不定期的会更新一些优质的算法题。如果对大家有帮助,别忘了三连支持哟!
目录
✨题目描述✨
💡:
描述:
输入一个数组,数组中只有两个元素出现了一次,其它元素均出现了两次。
示例:
输入:1,4,5,8,9,2,1,5,9,4
输出:8 2
✨题目分析✨:
在解决这道题目之前我们首先来了解一下按位异或运算符的一些操作
按位异或运算符
1:首先按位异或是位运算符,操作的是二进制的比特位
2:其具体运算过程可以记为:相同为0,相异为1,当然也可以理解为无进位加法
3:a^a=0 a^0=a
任何一个数按异或上自己为0,按位异或上0等于它本身
4:按位异或运算支持交换律和结合律
🔑:现在我们了解了按位异或操作符,在解决这个问题前,我们先解决它的简化版本:一个数组中只有一个元素出现了一次,其它元素均出现了两次
💎一个单身狗💎
🔑这题的难点就在于我们是否能正确的理解按位异或运算的操作符,其实按位运算有一个功能:
如果我们把数组中的所有元素按位异或起来,利用交换律和结合律把所有相同的聚在一起,这时如果出现偶数次的元素就会消除掉,出现偶数次的就会保留下来,因此我们遍历一遍数组,将所有元素按位异或起来,得到的结果就是那个只出现一次的数字。
int num = 0;//把只出现一次的数字放在num中去
void FindAppearSingalNum(int arr[], int sz)
{
int i = 0;
for (i = 0; i < sz; i++)
{
num ^= arr[i];
}
}
💎两个单身狗💎
🔑:在解决完一个单身狗后我们知道,我们可以遍历一遍数组,将数组中的所有元素按位异或起来,这样就可以消除出现偶数次的元素。但是有一个问题:
因为数组中有两个元素出现一次,所以遍历一遍后eor=num1^num2;其中num1和num2是那个只出现一次的数字。
1:由于数组中有两个单身狗,所以num1!=num2,这就保证了eor!=0,所以在eor的二进制序列中一定会有一个1.
2:因为eor是由num1^num2的结果,所以在eor二进制中从右往左数第一个1处,num1和num2
在这一比特位上一定存在不同,那么我们利用分治法,将数组中这一比特位上是1的元素分成一组,将数组中这一比特位是0的元素分成一组,我们可以保证在每一组中都有唯一一个单身狗,这样把每一组按位异或起来,就能得到这两个单身狗。
💡:现在这个问题就转化为了如何拿到eor中从右往左的第一个1
eor&(~eor+1)公式拿到二进制序列最右端的一个1
图解:
✨具体代码详解✨:
#include<stdio.h>
int num1 = 0;
int num2 = 0;
void FindAppearSingalNum(int arr[], int sz)
{
//1:遍历一遍将所有数都按位异或起来
int i = 0;
int eor = 0;
for (i = 0; i < sz; i++)
{
eor ^= arr[i];
}
//eor=num1^num2
//2:取出eor最右端的1作为区分值
int rightOne = eor & (~eor + 1);
for (i = 0; i < sz; i++)
{
if (rightOne & arr[i])
{
num1 ^= arr[i];
}
else
{
num2 ^= arr[i];
}
}
}
int main()
{
//测试用例
int arr[] = { 1,4,5,8,9,2,1,5,9,4 };
int sz = sizeof(arr) / sizeof(arr[0]);
FindAppearSingalNum(arr,sz);
printf("这两个单身狗是:%d %d\\n", num1, num2);
return 0;
}
以上代码,还可做优化在此仅作参考,若有更好的算法,还望能够私信告知,多谢各位。
由于本人水平十分有限,若有错误请即使告知!如果有帮助别忘了,万分感谢。
点赞👍 收藏✨ 关注✌
以上是关于你是真的“C”——找单身狗~的主要内容,如果未能解决你的问题,请参考以下文章
c++师傅领进门,修行靠个人第三篇:单身狗福利!!new一个属于你的对象