当前位置: 首页 > 科技观察

面试官:请说出四种不使用第三方变量交换两个变量值的方法

时间:2023-03-21 01:40:45 科技观察

大家好,我是阿Q。面试官:请告诉我几种不使用第三方变量交换两个变量值的方法。问题有点绕,好不容易弄明白面试官的问题,却发现自己答不上来。一时间尴尬至极,只能硬着头皮说不。当遇到交换变量值的问题时,我们通常的做法是定义一个新的变量,用它来完成交换。代码如下:t=a;a=b;b=t;但是问题的重点是“不要使用第三方变量”,那就变“可爱”了。想了想,抛出以下四种方法来解决这个问题:变量本身交换价值;算术运算;指针地址操作;位操作;变量本身交换价值b=(a+b)-(a=b);先执行a+b操作,然后将b赋值给a,则b=a+b-b=a,这样就完成了ab的交换操作。算术运算如图:OA=a;OB=b;AB=b-一个;首先我们将AB之间的距离b-a分配给a,然后AB=a,OB=b。要达到交换ab的目的,OA必须等于b,此时OA的距离为b-a,所以b-a必须赋值给b,此时OA=b,AB=a。从图中很容易看出OB的距离为b+a,所以我们只需要将b+a赋值给a就可以完成两者的交换。总结一下,我们的步骤是inta=10;intb=15;a=b-a;//b=15;a=5;b=b-a;//b=10;a=5;a=b+a;//b=10;a=15;该算法只能用于整数类型。指针地址操作我们可以把a和b看作内存中的地址值,假设a为0x01ff5e70,b为0x01ff5e90,b-a表示两个变量在内存中的存储位置之间相隔多少字节。所以我们理论上也可以按照算术运算的逻辑交换两个变量的值。代码如下(这里是c语言)://其中a和b是指针变量,存放10和20的地址int*a=newint(10);//a=0x01ff5e70,这里表示存放在a地址int*b=newint(20);//b=0x01ff5e90,这里表示b中存放的地址//指针变量减去20和10的地址之间有多少个字节,然后转换为指针变量a=(int*)(b-a);//b=0x01ff5e90;a=0x8b=(int*)(b-a);//b=0x01ff5e70;a=0x8a=(int*)(b+long(a));//b=0x01ff5e70;a=0x01ff5e90b-a=0x01ff5e90-0x01ff5e70=0x20,0x20转十进制是32位,因为一个int占4位,所以这里是0x8。以上只是理论状态下的执行过程,直接执行是无法实现兑换的。因为上面的代码忽略了一个问题:代码编译后,变量全部存放在内存中,基地址会存在内存区。基地址可以理解为一块内存的起始点。以上数据都是在基地址的基础上进行偏移的。变量的地址=变量的基地址+变量的偏移地址当我们进行b-a运算时,结果为8,然后在转换成指针变量时,会自动加上基地址到8,此时的结果已经不是0x8了,所以会导致错误的结果。另外,地址运算不能有负数,即当a的地址大于b的地址时,b-a<0,系统会自动用补码的形式表示负位移,并且也会出现错误。为了解决这个问题,我们只需要保证b-a的结果不受基地址的影响,所以给出了下面的解决方案。int*a=newint(10);int*b=newint(20);cout<