【c语言操作符系列1】^(异或操作符)讲解和多种例题详解

article/2025/11/6 5:47:05

 

目录

一、^ 是什么(^称为异或)

二、^的规律(特点)

三、可利用^秒杀的常见例题(重点)

1、消失的数字

 2、不一样的人生密码

3、交换两个数(不能创建中间变量)

4、找出只出现一个的两个数字


一、^ 是什么(^称为异或)

是一种操作符,针对二进制异或而言的,两个数对应的二进制位相同,异或结果为0,不同,异或结果为1。

例如:1^2

1的二进制位:

000000000 00000000 00000000 00000001

2的二进制位:

000000000 00000000 00000000 00000010

 1^2异或后: 

000000000 00000000 00000000 00000011 即为3

异或它在很多题型中都会用的到,我们利用它本身的常见规律可以秒杀很多题。


二、^的规律(特点)

特点1、大小相同的数字异或为0,任何数字异或0均为本身(可以自己写两个数的二进制位进行验证)

例如:1^1=0, 2^0=2 ,3^0=3

特点2、A^B^B = A 由1可得2 因为B^B=0 0^A=A

特点3、符合结合律和交换律


三、可利用^秒杀的常见例题(重点)

1、消失的数字

题目描述:数组nums包含从0到n的所有整数(nums是不重复的无序整形数组),但其中缺失了一个。请找出缺失的那个整数,时间复杂度最大为o(n)。

题目解释:比如n为3,那么nums数组本应包括0 1 2 3。但你现在可能就包含了0 1 3,假设丢了2( 但其中丢失哪一个你并不知道),就让你找丢失的这个2.

思路:0到n每个数^一遍,数组中存在的每一个元素^一遍,两者再^一下就找到缺失的数字了

比如n=3(假设数组中缺失了2),则0到n每个数^一下即 0^1^2^3

再^数组中存在的每一个元素:0^1^3

两者再^一下:0^1^2^3 ^ 0^1^3 = 2

这个是根据特点一和特点三推得,因为两个相同的数^后为0,一个数^0后=本身,所以就找到这个消失的数字了

代码如下:


#include<stdio.h>
int missingNumber(int* nums, int numsSize)
{int i = 0;int x = 0;for (i = 0; i <= numsSize; i++){x ^= i;}for (i = 0; i < numsSize; i++){x ^= nums[i];}return x;
}
int main()
{	//假设n为3int nums[] = { 0,1,3 };int n = 0;scanf("%d", &n);//数组的大小就是n,因为是0~n,本来应该有0 1 2 3的// 但现在只有0 1 3所以n就是数组此时的大小//如果不缺失一个数字,数组大小是n+1的printf("%d",missingNumber(nums, n));return 0;
}

 2、不一样的人生密码

题目描述:每个人都有一个人生密码,只有两个人的人生密码相同,才能走到一起,给出n个人的人生密码,n是奇数,其中只有一个人的人生密码是单独的,其他都是成对的,请你找出不成对的那一个。(时间限制400ms)

输入格式:

多组测试,每行第一个数为n(1<=n<=1000000),后面有n个正整数,表示n个人的人生密码,n值为0时表示输入结束。

输出格式:

输出那个不成对的人生密码。

输入样例:

3 8 9 8

5 120 10 120 10 85

0

输出样例:

9

85

思路:这道题跟第一题思路差不多,因为只有一个是单独的,那么把输入的所有数^一遍,得到的  不就是那个单独的数字,因为两个相同的数字^后一定为0,那个单独的数再^0一定得到那个    单独的数了 ,但是要考虑只有一个数字的话,就不用^了,直接找到了

代码如下:

#include<stdio.h>int main()
{int ret = 0, n = 0,i = 0,x = 0;while (~scanf("%d", &n) && n != 0){//判断这么写是因为&&具有左结合性ret = 0;//每组测试前一定要先初始化为0if (n == 1){//只有一个数就不需要^去掉成对的了scanf("%d", &x);printf("%d\n", x);continue;}for (i = 0; i < n; i++){scanf("%d", &x);ret ^= x;}printf("%d\n", ret);}return 0;
}

3、交换两个数(不能创建中间变量)

 题目要求:不能创建中间变量交换两个数

思路:运用特点二A^B^B=A和特点三的交换律即可求解

#include<stdio.h>
int main()
{int a = 0, b = 0;a = a ^ b;b = b ^ a;//b=b^ a^b=aa = a ^ b;//a=a^ a^b=breturn 0;
}

4、找出只出现一个的两个数字

题目描述:一个整形数组arr里除了两个数字只出现一次外,其他数字都出现了两次。请你找出这两个只出现一次的数字。要求时间复杂度:o(n),空间复杂度:o(1)。

如 int arr[] = {1,1,2,2,3,3,4,5,5,6,7,7,8,8,9,9}

则这两个你要找的数字为4,6

思路:要返回两个值,可以返回一个储存这两个值的数组,即指针。那么这道题其实就是在第二题不一样的人生密码上加了一点难度,第二题是找一个(找一个就很好处理了),而这道题是找两个。难就难在两个怎么处理,我们可以试试把这两个数字分离,转换成两组,每一组都是一道"不一样的人生数字"的题,即这两组,第一组包含了第一个只出现1次的数字,第二组包含了第二个只出现1次的数字。(因为只出现一次,说明这两个数肯定不相同,所以可以分离)。重点是如何分离

————  分离这两个数的过程  ————

我们只需找到这两个数不同的一个二进制位就可以,怎么找?两个数^后的结果中二进制位为1的,就说明两个数原来的这个位置的二进制位不同(肯定一个是0,一个是1) ,我们只需找到一个两者^后为1的二进制位即可。只要数组中元素对应的这个二进制位为1的数值分到一组,为0的分到另一组。我们就可以把这两个只出现一次的数区分为两组。那么这两组就变成:第一组有第一个数和其他n组成对的数,第二组有第二个数和其他m组成对的数。这下是不是就变成两个“不一样的人生密码”的例题2了吧?求两次是不是就可以了!

代码如下:

注:详细的代码理解全在代码中!

#include<stdio.h>
#include<stdlib.h>int* Find(int* arr, int numSize)
{
//1、得到两个只出现一次的数^后的结果int x = 0, i = 0;for (i = 0; i < numSize; i++){x ^= arr[i];//得到两个只出现一次的数的^后的结果}
//2、定位这个结果中一个二进制位为1时,需要x向右移多少位的mint m = 0;for (i = 0; i < 32; i++){//x是两个只出现一次的数^后的结果//x >> i & 1即这两个数不同的对应的一个二进制位数//而我们现在要找这个二进制位数是几,赋给mif ((x >> i & 1) == 1)//别忘了要加(),因为&优先级比==优先级低{//x>>i是遍历x的32位二进制位的意思,而我们要的是//x向右多少位的二进制才为1,我们找到一个二进制为1的即可m = i;break;}}
//3、将这两个只出现一次的数分为两组int x1 = 0, x2 = 0;for (i = 0; i < numSize; i++){if ((arr[i] >> m & 1) == 1){x1 ^= arr[i];//这一组中成对的数^后会变为0//所以x1最后的结果为两个出现一次的数的其中一个}if ((arr[i] >> m & 1) == 0){x2 ^= arr[i];//这一组中成对的数^后会变为0//所以x2最后的结果为两个出现一次的数的另一个}}
//4、创建数组返回这两个值int* a = (int*)malloc(sizeof(int)*2);//动态开辟,出了函数不会销毁//如果是静态开辟,出了函数,虽然原来a的地址还在,但是他的内容已经不属于a了//典型的返回栈空间地址带来的危害if (a != NULL){a[0] = x1;a[1] = x2;}elseexit(-1);return a;
}
int main()
{int arr[] = { 1,1,2,2,3,3,4,5,5,6,7,7,8,8,9,9 };int size = sizeof(arr) / sizeof(arr[0]);int* ptr = Find(arr, size);printf("%d %d", ptr[0], ptr[1]);free(ptr);ptr = NULL;return 0;
}


http://chatgpt.dhexx.cn/article/3tmKQY9i.shtml

相关文章

C语言中位运算异或“∧”的作用

前言&#xff1a; 为了方便查看博客&#xff0c;特意申请了一个公众号&#xff0c;附上二维码&#xff0c;有兴趣的朋友可以关注&#xff0c;和我一起讨论学习&#xff0c;一起享受技术&#xff0c;一起成长。 1.概念 异或运算符"∧"也称XOR运算符。它的规则是若参…

此公众号并没有这些scope的权限,错误码:10005

有时候在使用微信公众号时会出错&#xff0c;被告知没有权限&#xff0c;如下图所示&#xff1a; 出现这问题有以下原因&#xff1a; 订阅号没有相关的权限账号没有认证&#xff0c;没有相关的权限scope 参数位置错误 解决方案&#xff1a; 需要在OAuth2.0网页授权中配置授权…

Discuz 论坛 手机端微信登录报错:此公众号并没有这些scope的权限,错误码:10005

抛出问题 当discuz绑定微信公众号时&#xff0c;可以控制微信公众号的一些操作&#xff1a; 解决问题 而出现这种错误的原因一般由三种&#xff1a; 订阅号没有相关的权限账号没有认证&#xff0c;没有相关的权限scope 参数位置错误 排查问题&#xff1a; Discuz的微信…

10005---2017年国内开源项目Top50

国内开源项目&#xff0c;不错&#xff0c;大力支持&#xff0c;顶&#xff01;&#xff01;&#xff01; 我要是有钱&#xff0c;一定出资赞助他们啊。 2017 年度码云热门项目排行榜 TOP 50 出炉啦&#xff01;我们根据所有开源项目在码云的用户关注度、活跃度、访问量等信息…

Gurobi--Error code: 10005. Unable to retrieve attribute solved ‘Pi‘ 解决

Gurobi code 问题代码&#xff1a; 本来想获取变量的对偶空间&#xff0c; double[] dualmodel.get(GRB.DoubleAttr.Pi,model.getConstrs());但是报错&#xff0c;Error code: 10005. Unable to retrieve attribute ‘Pi’ 原因是在gurobi中&#xff0c;二进制变量&#xf…

此公众号并没有这些scope的权限 错误码10005

问题背景 看到好多原先可以的公众号忽然提示&#xff0c;“此公众号并没有这些scope的权限 错误码10005”。其实我也没真正解决。但是翻了论坛&#xff0c;为大家带来以下提示 解决方案

记录一次微信登录失败此公众号并没有这些 scope的权限,错误码:10005

在2023年4月17日&#xff0c;大概早上9:45分微信公众号出现 微信登录失败 此公众号并没有这些 scope的权限&#xff0c;错误码:10005 如下图&#xff1a; 经过网上查阅以及咨询微信开发的人&#xff0c;最终确认出是微信问题。刚开始其他公众号商家还没反馈到微信这个问题&…

Mysql出现问题:ERROR 1005 (HY000): Can‘t create table 解决方案

回城传送–》《数据库问题解决方案》 ❤️作者主页:小虚竹 ❤️作者简介:大家好,我是小虚竹。Java领域优质创作者🏆,CSDN博客专家🏆,华为云享专家🏆,掘金年度人气作者🏆,阿里云专家博主🏆,51CTO专家博主🏆 ❤️技术活,该赏 ❤️点赞 👍 收藏 ⭐再看,养成…

微信授权登录10005解决方案汇总

微信授权登录10005解决方案汇总 微信官方登录能力文档说明: https://developers.weixin.qq.com/community/develop/doc/000c840489c6380d63389dbb451402 微信授权登录报错10005的主要原因: 该图片文章来源: https://blog.csdn.net/qq_39702981/article/details/82703171 其次…

使用readelf分析一个elf文件完整结构

编译器编译源代码后生成的文件叫目标文件&#xff1b; 从结构上来说与可执行文件一致&#xff0c;只是还没有经过动态链接的过程&#xff0c;有符号还没有被调整。与真正可执行文件稍有区别。 可执行文件格式涵盖了程序的编译、链接、装载和执行的各个方面。 windows下的PE和…

GCC详解-Binutils工具之readelf

1、介绍 readelf从ELF 格式的目标文件显示信息。 readelf和objdump提供的功能类似&#xff0c;但是它显示的信息更为具体&#xff0c;并且它不依赖BFD库(BFD库是一个GNU项目&#xff0c;它的目标就是希望通过一种统一的接口来处理不同的目标文件) 2、ELF格式的文件 ELF&…

readelf命令使用

0x1、概述 readelf命令&#xff0c;一般用于查看ELF格式的文件信息&#xff0c;常见的文件如在Linux上的可执行文件&#xff0c;动态库(*.so)或者静态库(*.a) 等包含ELF格式的文件。以下命令的使用是基于android编译出来的so文件上面去运行。 0x2、readelf常用命令 语法&#x…

readelf的使用

记录下有接触到的使用。 这个命令可以用来查询可执行文件依赖什么动态库&#xff0c;查看静态库中包含了什么.o文件。 1、查询可执行文件依赖什么动态库 2、静态库中包含了什么.o文件

linux readelf,Linux readelf命令使用

readelf用来显示ELF格式目标文件的信息.可通过参数选项来控制显示哪些特定信息。 (注意: readelf不支持显示archive文档, 也不支持64位的ELF文件)。 使用方法1&#xff1a; 查看共享库的依赖库(NEEDED)和搜索名(SONAME)。 readelf -d 例如&#xff1a; #readelf -d libuClibc-…

Linux命令:readelf

1 需求 关键参数&#xff1a; -h/--file-header Display the ELF file header-l/--program-headers/--segments Display the program headers-S/--section-headers/--sections Display the sections header-s/--syms/--symbols Display the symbol table--dyn-sys…

readelf命令使用说明

0x1、概述 readelf命令&#xff0c;一般用于查看ELF格式的文件信息&#xff0c;常见的文件如在Linux上的可执行文件&#xff0c;动态库(*.so)或者静态库(*.a) 等包含ELF格式的文件。以下命令的使用是基于android编译出来的so文件上面去运行。 0x2、readelf常用命令 语法&…

readelf指令使用

一、指令说明 readelf命令&#xff0c;一般用于查看ELF格式的文件信息&#xff0c;常见的文件如在Linux上的可执行文件&#xff0c;动态库(*.so)或者静态库(*.a) 等包含ELF格式的文件。以下命令的使用是基于android编译出来的so文件上面去运行。 readelf常用命令 语法&#xff…

Mysql开发实践:error while loading shared libraries: libaio解决方案

摘要&#xff1a;Mysql出现问题&#xff1a;error while loading shared libraries: libaio解决方案。 本文分享自华为云社区《Mysql出现问题&#xff1a;error while loading shared libraries: libaio解决方案》&#xff0c;作者&#xff1a; 小虚竹。 问题 初始化数据库时…

fio: engine libaio not loadable

用测试工具fio&#xff0c;并且安装方式是源码编译安装。 tar xzf fio-fio-3.18.tar.gz && cd fio-fio-3.18 ./configure make make install编译安装完&#xff0c;想要测试顺序读、顺序写等时候&#xff0c;出现下面的报错&#xff1a; fio: engine libaio not loade…