平时写代码的过程之中,经常会有交换两个变量值的需求。然而我们大多数还是会采用借助额外变量的方式,因为这种方式不仅简单,容易理解,可读性高, 更重要的是适用范围广。那么今天我们来研究一下《如何不借助变量交换两个数》。
在正式解这道题之前,我们先用最基础的借助额外变量的方法来做一下。
JavaScript代码:
var a = 1;
var b = 2;
var temp = a;
a = b;
b = temp;
这个过程就像交换两个杯子中的水一样,如果不借助任何外物,显然我们不能用常规方法交换两个杯子的水。
但是问题转化为数字就变得有可能了 ,我们来看一下。
这是最容易想到的方法,整个过程我画了一个图。
JavaScript代码:
var a = 1;
var b = 2;
b = a + b;
a = b - a;
b = b - a;
但是 a 和 b 的和溢出的风险
,其实我们只要稍加变通一下即可。
我们来看下面的代码。
这个过程我同样画了一个图,可以看出这次没有出现3了。这在两个数字都非常大,以至于两个加起来 无法用数字表示的时候非常有用。
JavaScript代码:
var a = 1;
var b = 2;
b = a - b;
a = a - b;
b = a + b;
这种解法没有溢出的风险
,理论上已经非常完美了,难道还有更优的解法么?
我们来看一种更加高效的做法。
这里用到了异或这个位运算的性质,即相同则为 0,不同则为 1.
于是对于两个数字,a 和 b。则有 a ^ a ^ b 就等于 b
。我们可以利用这个性质来完成交换。
实际上,有些算法题就可以用这个性质轻松解决。
JavaScript代码:
var a = 1;
var b = 2;
b = a ^ b;
a = a ^ b;
b = a ^ b;
这个方法来自 大徒弟(@wuyuchang)的方法,这个方法利用了逗号表达式的性质。
什么是逗号表达式?逗号表达式是将两个及其以上的式子联接起来,从左往右逐个计算表达式,整个表达式的值为最后一个表达式的值。
因此我们可以利用这个性质,先完成一次赋值操作,然后将赋值操作的返回值变为0. 就可以完成赋值操作
JavaScript代码::
a = b + ((b = a), 0);
如果数字非常大怎么办?由于数字非常大, 因此我们不能用数字存储了(也不能用 Bit Int)。我们只能使用别的方式存储,比如字符串。这个时候我们不能转化为数字,然后做四则运算, 那么我们怎么办?
这个其实我们可以自己实现一个“加法”或者“减法”,然后思路就和上面一样了。关于这部分,可以参考大数相加[1] 和 实现加法[2]
[1]
大数相加: https://lucifer.ren/fe-interview/#/./topics/algorthimn/bigNumberSum
[2]
实现加法: https://lucifer.ren/fe-interview/#/./topics/algorthimn/bitTwoSum