【巧用异或】单身狗2题解

 ✨✨欢迎大家来到Celia的博客✨✨

🎉🎉创作不易,请点赞关注,多多支持哦🎉🎉

所属专栏:【每日刷题】C语言

个人主页:Celia's blog~

 题目

一个数组中只有两个数字是出现一次,其他所有数字都出现了两次。

编写一个函数找出这两个只出现一次的数字。

例如:

有数组的元素是:1,2,3,4,5,1,2,3,4,6

只有5和6只出现1次,要找出5和6.

解题思路 

 这道题可以巧用异或的方式来解答,在此之前,让我们先来了解异或操作符的运算法则:

异或(^):用二进制形式对比两个变量的每一位,如果不同则为1,如果相同则为0。

我们可以得到以下重要推论:

  • n^n=0
  • 0^n=n

 了解了异或操作符的运算法则后,我们可以在此基础上列出此题的大致思路:

先简化一下问题:

如果有一个数组其中只有一个元素单独出现,其他都是成对出现,找出单独出现的元素。

int arr[]={1,2,3,4,5,1,2,3,4};

我们可以遍历这个数组的每一个元素进行异或操作:

int sz = sizeof(arr)/sizeof(int);
int i, ret = 0;//ret初始化为0,这样能保证ret^arr[0]的值为数组第一个元素
for(i = 0; i < sz; i++)
{ret ^= arr[i];
}

异或运算符是符合交换律的,遍历一次后相当于上图的操作,最后剩下的就是只出现一次的数字了。

这个简化后的版本和本题的区别是:简化的版本只有一个元素单独出现,本题有两个元素单独出现。我们只需要把本题中的数组分为两组,每一组只有一个元素单独出现,每一组都利用上文的方法,就可以解决此题。那么问题又来了,该按何种方法进行分组呢?

以下是大致思路:

  1. 既然有两个数单独出现,那么单独出现的这两个数一定是不同的两个数。
  2. 既然是不同的两个数,在二进制位上一定有一个或者多个位数是不同的。
  3. 我们可以记录这两个数到底是在第几位二进制数位上是不同的,并且找出其中一个的位置。
  4. 按照这个位置为0或者为1对数组中所有的数进行分组。

有了解题思路,那就先进行第一步:找出这两个数在二进制位上哪个位置是不同的。我们仍然可以遍历数组的每一个元素进行异或操作,这样一来,成对出现的数字互相异或的结果为0,最后剩下的就是两个不同数字异或的结果,这个结果在二进制位上 ‘1’ 的位置就是我们要找的位置。

int arr[]={1,2,3,4,5,1,2,3,4,6};
//5和6只出现一次,其他数字成对出现
int sz = sizeof(arr)/sizeof(int);
int i, ret = 0;
for(i = 0; i < sz; i++)
{ret ^= arr[i];//最后是5^6的结果
}

 接下来我们要确定这两个数在二进制的第几位是不同的,确定其中一个位置即可

 for (i = 0; i < 32; i++)//最多有32位{if (((ret >> i) & 1) == 1)//右移检查每一个二进制位,与1按位与如果等于1,说明这个二进制位为1{//ret二进制位上的‘1’即为两个数二进制位上的不同之处flag++;//二进制位上的数只有0和1两种可能,找到一个不同之处即可,凭此即可区分两个数。break;}}
//以下代码为自定义函数中的代码片段
for (i = 0; i < sz; i++)
{if (((arr[i] >> flag) & 1) == 1)//将数组中的每一个元素右移flag位进行判断{*p1 ^= arr[i];//p1最终的结果将保存第一个单独出现的数,p1初值为0}else*p2 ^= arr[i];//p2最终的结果将保存第二个单独出现的数,p2初值为0
}

这样就变相的将数组中的元素分为两组分别进行遍历异或操作,最终得出结果。

完整代码

#include <stdio.h>
void find_dog2(int arr[10], int* p1, int* p2,int sz)
{int i, flag = 0, n = 0;for (i = 0; i < sz; i++){n ^= arr[i];}for (i = 0; i < 32; i++){if (((n >> i) & 1) == 1){flag++;break;}}for (i = 0; i < sz; i++){if (((arr[i] >> flag) & 1) == 1){*p1 ^= arr[i];}else*p2 ^= arr[i];}
}
int main()
{int arr[10] = { 1,2,3,4,5,1,2,3,4,6 };int p1 = 0, p2 = 0;int sz = sizeof(arr) / sizeof(int);find_dog2(arr, &p1, &p2,sz);printf("第一个数字是:%d,第二个数字是:%d", p2, p1);return 0;
}

以上就是本题题解的全部内容啦~

如果觉得有所收获的话,记得点赞关注支持一下~

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.hqwc.cn/news/449325.html

如若内容造成侵权/违法违规/事实不符,请联系编程知识网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

spring boot yaml文件中如何设置duration对象值

Spring Boot对表示持续时间有专门的支持。如果您公开java.time.Duration属性&#xff0c;则应用程序对应Duration类型的属性有以下格式可用: long类型的常规表示(使用毫秒作为默认单位&#xff0c;除非指定了DurationUnit)java.time.Duration 使用的标准ISO-8601格式其中值和单…

Leetcode—2881. 创建新列【简单】

2024每日刷题&#xff08;一零九&#xff09; Leetcode—2881. 创建新列 实现代码 import pandas as pddef createBonusColumn(employees: pd.DataFrame) -> pd.DataFrame:employees[bonus] employees[salary] * 2return employees 运行结果 之后我会持续更新&#xf…

第十一章[文件系统]:11.1:文件的读写

一,文件的读取 1,open()函数 open()函数: 功能:open() 函数用于打开一个文件,并返回文件对象, 在对文件进行处理过程都需要使用到这个函数, 如果该文件无法被打开,会抛出 OSError。 open(file, mode=r) 参数:file: 必需,文件路径(相对或者绝对路径) mode: 可选,文…

大模型实践笔记(1)——GLM-6B实践

目录 在Ubuntu上的配置Git Large File Storage 安装Git LFS&#xff1a; 设置Git LFS&#xff1a; 使用Git LFS&#xff1a; 安装GLM-6B 环境依赖 ChatGLM2-6B介绍 配置GLM 下载代码 构建环境 安装依赖 本地部署 网页UI 很多模型在hugging face上面&#xff0c;…

线性代数:线性方程组

目录 一、线性方程组概念 二、消元法求线性方程组 三、系数阵的秩与线性方程组的解 无解 唯一解 无数解 相关定理 一、线性方程组概念 二、消元法求线性方程组 三、系数阵的秩与线性方程组的解 无解 唯一解 无数解 相关定理

【笔记】React Native实战练习(仿网易云游戏网页移动端)

/** * 如果系统看一遍RN相关官方文档&#xff0c;可能很快就忘记了。一味看文档也很枯燥无味&#xff0c; * 于是大概看了关键文档后&#xff0c;想着直接开发一个Demo出来&#xff0c;边学边写&#xff0c;对往后工作 * 开发衔接上能够更顺。这期间肯定会遇到各种各样的问题&a…

STM32F407移植OpenHarmony笔记8

继上一篇笔记&#xff0c;成功开启了littlefs文件系统&#xff0c;能读写FLASH上的文件了。 今天继续研究网络功能&#xff0c;让控制台的ping命令能工作。 轻量级系统使用的是liteos_m内核lwip协议栈实现网络功能&#xff0c;需要进行配置开启lwip支持。 lwip的移植分为两部分…

计算机图形学 实验

题目要求 1.1 实验一&#xff1a;图元的生成&#xff1a;直线、圆椭区域填充 你需要完成基本的图元生成算法&#xff0c;包括直线和椭圆。 在区域填充中&#xff0c;要求你对一个封闭图形进行填充。你需要绘制一个封 闭图形&#xff08;例如多边形&#xff09;&#xff0c;并选…

HTTP和HTTPS区别!

http 是我们几乎天天都要打交道的东西&#xff0c;相关知识点有点多&#xff0c;所以也有不少面试必问的点&#xff0c;这里做了一些整理&#xff0c;帮且大家树立完整的 http 知识体系&#xff0c;对面试官说 so easy HTTP 的特点和缺点 特点&#xff1a;无连接、无状态、灵…

网络时间协议NTP工作模式

单播服务器/客户端模式 单播服务器/客户端模式运行在同步子网中层数较高层上。这种模式下,需要预先知道服务器的IP地址。 客户端:运行在客户端模式的主机(简称客户端)定期向服务器端发送报文,报文中的Mode字段设置为3(客户端模式)。当客户端接收到应答报文时,客户端会…

MATLAB拟合正态分布(附完整代码和数据)

使用MATLAB拟合正态分布的主要步骤是: 输入样本数据 使用变量x保存样本数据,例如: x [1.2, 3.4, 2.1, 0.5, 4.3]; 调用正态分布的最大似然估计函数 使用normfit函数来完成正态分布的参数的最大似然估计: [mu_hat,sigma_hat] normfit(x); normfit函数会返回正态分布位置…

查看自己电脑是arm还是x64(x86)

linux 参考&#xff1a; https://liuweiqing.blog.csdn.net/article/details/131783851 uname -a如果输出是 x86_64&#xff0c;那么你的系统是 64 位的 x86 架构&#xff08;通常我们称之为 x64&#xff09;。如果输出是 armv7l 或者以 arm 开头的其他值&#xff0c;那么你的…