问题:怎么不使用第三个变量交换两个变量的值呢?
解决方案1——数学计算:
1、猜想:
用脚丫想到,似乎加减乘除就能做到这件事吧。然后想一下,如果用乘法很容易爆Int,而且都乘大了,减回来明显不靠谱,除回来除什么?有余数怎么办?也不靠谱。于是基本策略就是只用加减法,那么不妨试一下(a+b)和(a-b)之类的运算,来找一找规律。
2、推理:
于是我在纸上写下了:
a = a + b
很明显我发现这是程序语言的写法,左边 a 和右边 a 不好区分,不易推理,于是改成了:
a1 = a0 + b0
a0 和 b0 表示 a 和 b 的初始值,当推理到某一步时若发现:an = b0, bm = a0,则说明交换成功。但切记推理过程中一定要记得这样一点:同字母的变量会被新的赋值覆盖,或者说同字母的变量里只有最新的是有效的。那么接下来不难想到:
b1 = a1 - b0 = a0
那么很明显最后一步:
a2 = a1 - b1 = b0
证毕。
3、实现代码:
<span style="font-family:Microsoft YaHei;">void mySwap_1(int &a, int &b){
a = a + b;
b = a - b;
a = a - b;
}</span>
解决方案2——位运算:
1、猜想:
每个数字都可以表达成 2 进制,即用一串 0、1 表示,那么可不可以通过交换两个数字的 0、1 值来实现交换两个数的值呢?
2、推理:
两个数字放在一起,比较它们的二进制各位中的某一位,无非有四种情况:都是0、都是1、1和0、0和1(后两者其实一样,此处为方便考虑)。不妨举出一个四者皆有的例子,来方便我们思考:
a = 1 0 1 0
b = 1 0 0 1
好的,写在纸上很明显,我们一眼就能发现:若想交换 a、b 的值,则相同位不用变,不同位与自己原来取反即可。同时这个例子列举全了四种情况,例子成功了算法就成功了。接下来,“相不相同、不变、反转”,说到这些想到了什么,没错,就是异或!因为异或运算有这样的特征:
① 相同得 0,不同得 1,可以告诉我们哪些位相同哪些位不同。
② 不管 0 还是 1,与 0 异或都不变
③ 不管 0 还是 1,与 1 异或都反转
那么我们异或一下试试吧:
a1 = a0 ^ b0 = 0 0 1 1
好的,a1 中的 0 表示二者相同,1 表示二者不同。那么 b 直接与 a1 异或,就可以做到相同位不变,不同位取反了:
b1 = b0 ^ a1 = b0 ^ a0 ^ b0 = a0
接下来:
a2 = b1 ^ a1 = a0 ^ a0 ^ b0 = b0
3、实现代码:
void mySwap_2(int &a, int &b){
a = a ^ b;
b = b ^ a;
a = b ^ a;
}
PS:太久没写C++,使用引用作为函数参数这件事我都忘差不多了。。引用是啥都说不清了,对引用进行操作就像对原变量进行操作是一样的。好吧,我会找时间写一篇博客专门深入研究一下。