异或运算在面试题中的应用

异或运算 是 涉及到数据位运算时常见的处理方式。如何进行异或运算?在对应位上,相同为0,不同1,但其实两个数据异或运算就是进行无进位加法

例如: int a = 7, b = 6,  a ^b = ?

算法1: 相同为0,不同为1

                     

                                                            a ^ b=  :     0         0         0         1

算法2: 无进位相加

                    

                                                             a ^ b=  :     0         0         0         1

异或运算的性质

1)0^N == N  

2)  N^N == 0

3)  异或运算满足交换律和结合律  

       交换律: a^b = b^a

       结合律:a^b^c = a^(b^c)

题目1:如何不用额外变量交换两个数?

//代码段1

#include <stdio.h>

void swap(int* a, int i, int j){
    a[i] = a[i]^a[j];
    a[j] = a[i]^a[j];
    a[i] = a[i]^a[j];
}

int main(){
    
    return 0;
}

代码解析:

为什么执行了 a = a^b; b = a^b; a= a^ b; 这三句代码,a和b的值就被交换了?

设:变量 a = A, b = B;

a = a ^ b;   \Rightarrow a = A^B,  b = B;

b = a ^ b;   \Rightarrow b = B^A^B,  由于异或运算满足交换律,所以,b = B^B^A , 又因为N^N == 0 且 0^N = N, 所以,b = A;

a = a ^ b;   \Rightarrow a = A^B^A = B

Tip:

        如果使用异或运算交换数据 a 和 b的值, a 和 b的值 可以相等,但是二者必须指向不同的内存空间,不能是同一个变量。例如在代码段1中,交换数组a[i] 和a[j] 的值 ,  a[i] 可以等于 a[j] (a[i] == a[j] == X),但是 i 不可以等于j,因为,如果 i== j , a[i] ^ a[j]  \Rightarrow a[i]  ^ a[i]  , 根据异或运算的性质,一个数与其自身进行异或运算,结果为0(N^N=== 0). 所以 如果 i 等于 j ,执行了swap函数后,a[i]  和 a[j] 都将被置0.

题目2:一个数组中有一种数出现了奇数次,其他数都出现了偶数次,找到并打印这种出现了奇数次的数。

题目解析:

这道题同样是异或运算的性质的应用:N^N == 0 和 0^N == N 

两个N异或等于0,那么n个N异或呢?即 N^N^N...^N = ? 结果显而易见,如果n为偶数,那么结果就是0,如果是n为奇数,那么这个连续异或的式子就最终简化为 0 ^N , 继续利用异或的性质,这个结果为N。

综上分析,如果把这个数组中的数据依次执行异或运算, 假设数组名为a, 那么

a[0]^ a[1] ^ a[2] ^ ... a[n]  最终结果就是 0 ^ a[i] , a[i] 即为出现了奇数次的那个元素。

代码实现:

//代码段2

#include <stdio.h>

int findOdd(int* a , int n){
    int eor = 0;
    for(int i = 0;i < n;i++){
        eor ^= a[i];
    }
    return eor;
}
int mian(){

    int a[11] = {1,1,1,1,2,2,3,3,3,3,3};
    printf("odd is %d\n",findOdd(a,11));
    return 0;
}

 运行结果:

 题目3:如何把一个int类型的数,提取出最右侧的1?

题目解析

题目要求将一个int类型的数的最右侧的1提取出来,那么必然涉及将int型数的二进制表达及相关位运算。例如:int a = 0110 1110 0100 0000, 根据题目要求,要找到它最右侧的1,那么得到的结果应该是 ans = 0000 0000 0100 0000 ,对其它数位的情况并不关心。

如何通过 a 得到结果ans 呢? 即  a \to ans  需要经过怎样的运算? ans = a & (~a +1)

因为ans 要求除了a的最右侧的1保留,其它位上都为0, 而一个数与它的相反数做“与”操作,结果就是0,但是最右侧的1被保留,就说明除了最右侧1这一位,其它位都是与其相反数做了“与”操作,因此 (~a+1)就是使a的最右侧1这一位在与反后,又被置成了1.

                            a =  0110 1110 0100 0000

                          ~a = 1001 0001 1011 1111

                      ~a+1 = 1001 0001 1100 0000

             a & (~a+1) = 0000 0000 0100 0000

 代码实现:

//代码段3
#include <stdio.h>

int findRight_1(int a){
    return a & (~a+1)
}

另:(~a+1 )其实就是-a , 代码段3可以写成代码段4,结果是一样的。

//代码段4
#include <stdio.h>

int findRight_1(int a){
    return a & (-a)
}

题目4: 一个数组中有两种数出现了奇数次,其他数都出现了偶数次,怎么找到并打印这两种数?

题目解析:

经过题目2的分析,我们知道如果将这个数组从头到尾的异或一遍,出现了偶数次的数被销掉了,结果为 eor = a ^ b , a 和 b是出现了奇数次的两种数,因为题目明确说了出现奇数次的是两种数,那么 a 不等于 b,所以 eor就不等于0。从左往右依次查看eor每一个bit位,肯定有一个bit位是1,假设是第i位 , 进一步假设a 的第i位是1, b的第 i 位是 0 。那么,原数组就可以分成两类,第一类为第i位是1的数,第二类为第i位是0的数。

第一类:数组中第 i 位 是 1的数第二类: 数组中第 i 位是 0 的数
ab
出现了偶数次且 第 i 位是 1的数出现了偶数次且 第 i 位是 0的数

如果将第一类中的数,从头到尾执行一遍异或运算,会发生什么?"出现了偶数次且第i位为1的数” 依然化为零被销掉了,结果是  {eor}' = a 

同理,将第二类中的数,从头到尾执行一遍异或运算,“出现了偶数次且第 i 位为0 的数” 被销掉,结果 {eor}'' = b.  但是,在求b时 可以利用eor的结果: {eor}'' = eor ^ {eor}' 

难点:

1. 将数组从头到尾执行一遍异或运算 ,结果为 eor 

1. 找到eor 结果中最右端第一个1 的bit 位 :bit_i .  (这个问题就可以利用题目3 的思路)

2. 遍历数组,找到bit_i 位上都为1 的数据,并保存到数组B;

3 将数组B 从头到尾执行一遍异或运算,结果{eor}' 就是其中一个奇数次 数;

{eor}'' = {eor}' ^ eor , 得到另一个奇数次数

代码实现

#include <stdio.h>

/* arr :  待处理数组
   n:arr长度
   a:出现奇数次的数据1
   b:出现奇数次的数据2
*/
void findOdd_2(int* arr, int n, int* a, int* b){
    int eor = 0;
    for(int i = 0;i < n;i++){
        eor ^= arr[i];
    }
  
    int bit_1 = eor & (-eor); //提取最右侧的1
 
    int eor_a = 0;
 
    for(int i = 0;i < n;i++){
       if(arr[i] & bit_1){
           eor_a ^= arr[i];
       }
    }

    *a = eor_a;
    *b = eor_a ^ eor;
}
 
int main(){
    int arr[16] = {12,12,12,19,19,19,13,13,13,13,45,45,66,66,66,66};
    int a = 0, b = 0;
    findOdd_2(arr,16,&a,&b);
    printf("a = %d, b = %d\n",a,b);
    return 0;
 }

运行结果:

题目5: 一个数组中有一种数出现K次,其他数都出现了M次,M>1, K<M, 请找到出现了K次的数,要求额外空间复杂度为O(1) ?

题目解析:

首先利用一个实例来进一步解释题目:假设数组A中共有4种数,a, b ,c ,d, 其中,a 出现了k次,b、c 和d 都出现了M次, M>1, k<M.

题目5与题目4很相似,都是根据元素在数组中出现的次数来确定元素值,但是题目5中并未明确数据出现次数的具体值。一个整型数是32个bit位,定义一个大小为32 的数组 int  arr[32] ,  arr[i] 表示原数组中 第i位为1 的数据元素的总和,例如,数组A中:

a的第i位 为1,b的第i位为1,c 和 d 的第i位为0,则 arr[i] = 1*K+ 1*M +0+0 = k+M;

a的第i+1 位1,b的第i+1位位1, c 的第i+1位为1, d的第i+1位为0, 则 arr[i+1] = K+M+M+0 = k+2M;

以此类推,计算出arr中 0~31 个元素的值。

再逆向思考,如果 arr[i] % M == 0 ,说明数组A中只有出现M次的元素在arr[i] 上是1;arr[i] % M !=  0, 说明数组A中出现K次的元素在arr[i] 为1. 

代码实现:

#include <stdio.h>

int findK(int* arr, int n, int k, int M){
    int bit32[32] = {0};
    for(int i = 0;i < n;i++){  //遍历数组arr中的每个元素
        for(int j = 0; j < 32;j++){ //遍历arr[i] 的32个bit位
            bit32[j] += (arr[i]>>j) & 1; //如果arr[i]的第j个bit位为1,则bit[j] 加1;
        }
    }
    int ans = 0; //出现k次的数据
    for(int i = 0;i < 32;i++){ //遍历数组bit32
        if(bit32[i] % M){ //如果bit[i]% M 不为0,说明在出现K次的数据在第i个bit位上是1
            ans += 1 << i; //将出现k次数据的第i个bit位置为1
        }  
    }
    return ans; 
}

总结:对异或运算的考察,主要是对其性质的考察,在实际问题中能够灵活的运用其性质。 上述题目5虽然没有使用异或运算,但是给我们提供了一种利用位运算解决问题的思路。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

边界内聚和耦合

内聚 功能内聚 功能内聚是软件工程中一个重要的概念&#xff0c;它描述了一个模块内部各个元素之间的紧密程度。一个具有高功能内聚的模块意味着其内部的各个组件都共同完成一个具体的、明确的功能&#xff0c;并且这些组件之间的联系不是偶然的&#xff0c;而是因为它们共同服…

sslscan一键检测服务器协议信息和加密算法(KALI工具系列二十四)

目录 1、KALI LINUX 简介 2、sslscan工具简介 3、信息收集 3.1 目标主机IP&#xff08;服务器&#xff09; 3.2 KALI的IP 4、操作示例 4.1 扫描主机 4.2 指定端口 4.3 输出详细信息 4.4 打印输出信息 4.4 检测协议 5、总结 1、KALI LINUX 简介 Kali Linux 是一个…

在下游市场需求带动下 我国聚天门冬氨酸脂防腐涂料市场规模不断扩大

在下游市场需求带动下 我国聚天门冬氨酸脂防腐涂料市场规模不断扩大 聚天门冬氨酸酯防腐涂料又称为天冬聚脲防腐涂料&#xff0c;是以聚天门冬氨酸酯作为主体树脂、脂肪族异氰酸酯为固化剂而形成的一种防腐涂料。与其他类型的防腐涂料相比&#xff0c;聚天门冬氨酸酯防腐涂料具…

IO系列(十) -TCP 滑动窗口原理介绍(上)

一、摘要 之前在上分享网络编程知识文章的时候&#xff0c;有网友写下一条留言&#xff1a;“可以写写一篇关于 TCP 滑动窗口原理的文章吗&#xff1f;”。 当时没有立即回复&#xff0c;经过查询多方资料&#xff0c;发现这个 TCP 真的非常非常的复杂&#xff0c;就像一个清…

《TCP/IP网络编程》(第十五章)套接字和标准I/O

之前数据通信时&#xff0c;使用的是read&write函数以及其他各种I/O函数&#xff0c;本章将使用标准I/O函数&#xff0c;例如C语言的fopen、fgetc、fputs等等&#xff1b;C语言的cout、cin等等 1.使用标准I/O函数的优点 ①跨平台兼容性&#xff1a; 标准I/O函数通常是跨平…

依赖自动装配

黑马程序员SSM框架 文章目录 1、依赖自动装配2、依赖自动装配的特征 1、依赖自动装配 IoC容器根据bean所依赖的资源在容器中自动查找并注入到bean中的过程称为自动装配自动装配方式 按类型&#xff08;常用&#xff09;按名称按构造方法不启用自动装配 配置中使用bean标签auto…

68. UE5 RPG 优化敌人角色的表现效果

我们现在已经有了四个敌人角色&#xff0c;接下来&#xff0c;处理一下在战斗中遇到的问题。 处理角色死亡后还会攻击的问题 因为我们有角色溶解的效果&#xff0c;角色在死亡以后的5秒钟才会被销毁掉。所以在这五秒钟之内&#xff0c;角色其实还是会攻击。主要时因为AI行为树…

flash介绍(zynq篇)

简介&#xff1a;Flash存储器&#xff08;又称闪存&#xff09;是一种非易失性存储器. 页是读写的基本操作单位。&#xff08;页写前需要进行擦除操作&#xff08;全部为1&#xff09;&#xff0c;写操作是实现1→0操作&#xff09; 注意&#xff1a;zynq中有板载flash控制器的…

服务部署:Linux系统部署C# .NET项目

1. 安装 .NET SDK 首先&#xff0c;你需要在你的 Linux 系统上安装 .NET SDK。 Ubuntu系统&#xff1a; 下载 Microsoft 包配置文件 wget https://packages.microsoft.com/config/ubuntu/20.04/packages-microsoft-prod.deb -O packages-microsoft-prod.deb 这个命令使用 wge…

大模型Prompt-Tuning技术入门

Prompt-Tuning方法 1 NLP任务四种范式 目前学术界一般将NLP任务的发展分为四个阶段&#xff0c;即NLP四范式&#xff1a; 第一范式&#xff1a;基于「传统机器学习模型」的范式&#xff0c;如TF-IDF特征朴素贝叶斯等机器算法&#xff1b;第二范式&#xff1a;基于「深度学习模…

java打印99乘法表

public class NineNineMulTable{public static void main(String[] args){for(int i 1; i < 9; i ){for(int j 1; j < i; j ){System.out.print(j " * " i " " i * j "\t");//再次先输出j在输出i是打印出来是1*2&#xff0c;2*2}S…

网络安全技术实验六 入侵检测技术实践

一、实验目的和要求 理解基于网络的入侵检测系统的基本原理&#xff0c;掌握snort IDS工作机理&#xff1b; 学习应用snort三种方式工作&#xff1b;熟练编写snort规则&#xff1b; 完成snort数据包记录、日志查看、字符串匹配、ARP欺骗攻击检测、端口扫描工具检测等功能。 …

【计算机视觉】人脸算法之图像处理基础知识(二)

图像处理基础知识&#xff08;二&#xff09; 1.图像的颜色空间转换 我们常见的图像通常由R&#xff08;红色&#xff09;、G&#xff08;绿色&#xff09;、B&#xff08;蓝色&#xff09;组成。但是在很多时候我们会将彩色图像转换成灰度图像进行处理。此时会用到cv2.cvtCo…

C#观察者模式应用

目录 一、什么是观察者模式 二、C#中观察者模式的实现 三、两种实现的用法 1、事件与委托 2、IObserver和IObservable 四、参考文献 一、什么是观察者模式 观察者&#xff08;Observer&#xff09;模式的定义&#xff1a;指多个对象间存在一对多的依赖关系&#xff0c;当…

AGI 远不止 ChatGPT!一文入门 AGI 通识及应用开发

AI 大语言模型进入爆发阶段 2022 年 12 月 ChatGPT 突然爆火&#xff0c;原因是其表现出来的智能化已经远远突破了我们的常规认知。虽然其呈现在使用者面前仅仅只是一个简单的对话问答形式&#xff0c;但是它的内容化水平非常强大&#xff0c;甚至在某些方面已经超过人类了&am…

WordPress插件数据库批量替换内容工具插件

1、安装插件后&#xff0c;我们就可以在后台菜单看到工具操作界面 2、目前支持网站内容、标题、评论指定字符的快速替换 3、可以快速解决以往我们需要从MYSQL数据库命令替换的烦恼

聊聊DoIP吧(三)-端口号port

DoIP在UDP和TCP建立连接和发送诊断报文的过程中使用的端口定义如下&#xff1a;

通过腾讯云TDSQL TCPTCE(MySQL版)认证考试秘籍宝典

腾讯云TDSQL(MySQL版)交付运维高级工程师TCCP证书展示 腾讯云TDSQL(MySQL版)交付运维专家TCCE考试成绩、证书展示 认证类型与级别 TCCA:入门级(初级) TCCP:高级(中级) TCCE:专家级(高级) 考试形式 考试是在线考试&#xff0c;考生需要在腾讯云大学官网上完成。 腾讯云TDSQ…

最新情侣飞行棋高阶羞羞版,解锁私密版情侣小游戏,文末有福利!

今天要跟大家聊聊一种特别有意思的游戏——情侣飞行棋羞羞版。别急着脸红&#xff0c;这可是专为情侣设计的游戏&#xff0c;让你们在轻松愉快的氛围中&#xff0c;增进了解&#xff0c;加深感情。 谈恋爱&#xff0c;不就是两个人在一起&#xff0c;做些有趣的事情吗&#xf…

鸿蒙开发:【设置任务快照的图标和名称】

设置任务快照的图标和名称 设置任务快照的图标和名称是为了提高用户界面的可视化性和用户体验&#xff0c;以便更好地管理和跟踪应用程序中的任务和功能。通过为每个任务快照设置不同的图标和名称&#xff0c;可以更轻松地区分和识别每个任务的功能。 默认情况下任务快照的图…