很多算法都需要交换2个变量。
在编码面试中,你可能会被问到*"如何在没有临时变量的情况下交换2个变量?"。*
了解执行变量交换的多种方法是很好的。在这篇文章中,你将读到4种交换的方法(2种使用额外的内存,2种不使用)。
1.解构赋值
解构赋值(ES2015的一个特性)让你可以将数组中的项目提取到变量中。例如,下面的代码是对一个数组进行析构。
let a;
let b;
[a, b] = [1, 2, 3];
a; // => 1
b; // => 2
知道了如何解构数组,就很容易用它来交换变量了。让我们用结构化赋值来交换变量a 和b 。
javascript
let a = 1;
let b = 2;
[a, b] = [b, a];
a; // => 2
b; // => 1
在第一步,在析构的右侧,创建了一个临时数组 [b, a] (其值为[2, 1] )。
然后对临时数组进行解构:[a, b] = [2, 1] 。变量a 被分配给2 ,b 被分配给1 。a 和b 的互换已经完成。
我喜欢去结构化的方法,因为它简短而富有表现力:只用一条语句就能完成交换。它适用于任何数据类型:数字、字符串、布尔运算、对象。
我建议在大多数情况下使用结构化赋值来交换变量。
2.临时变量
使用临时变量来交换变量是很经典的。顾名思义,这种方法需要一个额外的临时变量。
让我们使用一个临时变量a 和b 来交换变量的值,temp 。
javascript
let a = 1;
let b = 2;
let temp;
temp = a;
a = b;
b = temp;
a; // => 2
b; // => 1
temp 是临时变量。
在第一步,temp 被分配到a 的值。然后a 变量被分配到b 的值。最后,变量b 被分配到temp 的值(初始值为a )。
使用临时变量交换变量的方法适用于任何数值类型,如数字、字符串、布尔、对象。
这种方法的缺点是需要一个专门的临时变量,加上交换发生在3条语句中。
3.加法和差分
你可以不使用额外的内存(如临时数组或变量)来交换变量。
下面的例子使用加法+ 和差法- 算术运算符交换了变量a 和b 。
javascript
let a = 1;
let b = 2;
a = a + b;
b = a - b;
a = a - b;
a; // => 2
b; // => 1
最初,a 是1 ,b 是2 。让我们看看这3个语句是如何进行互换的。
a = a + b分配给 的值是 。a1 + 2b = a - b给 赋值为 ( 现在是 )。b1 + 2 - 2 = 1``b1a = a - b给 赋值 ( 现在是 )。a1 + 2 - 1 = 2``a2
最后,a 是2 ,b 是1 。a 和b 的互换已经完成。
虽然这种方法不使用临时变量,但它有相当大的限制。
首先,你只能调换整数。其次,在第一步a = a + b 进行加法时要注意数字的溢出(总和必须低于Number.MAX_SAFE_INTEGER )。
4.位数XOR运算法则
如果操作数不同,XOR运算符的评估结果为真。作为提醒,这里是XOR真值表。
┌─────┬─────┬───────┐
│ a │ b │ a ^ b │
├─────┼─────┼───────┤
│ 0 │ 0 │ 0 │
│ 1 │ 1 │ 0 │
│ 0 │ 1 │ 1 │
│ 1 │ 0 │ 1 │
└─────┴─────┴───────┘
在JavaScript中,位数XOR运算符n1 ^ n2 对n1 和n2 的每一位数字进行XOR运算。
例如,这里是5 ^ 7 如何评估为2 。
1 0 1 (5 in binary)
1 1 1 (7 in binary)
-----
0 1 0 (5 ^ 7 = 2 in binary)
位向XOR有两个有趣:
n ^ n = 0:在同一个数字上进行的位向XOR是0n ^ 0 = n:在一个数字和零上进行的位数XOR是同一个数字
这些XOR属性可以用来交换变量。让我们看看如何交换a 和b 变量。
javascript
let a = 1;
let b = 2;
a = a ^ b;
b = a ^ b;
a = a ^ b;
a; // => 2
b; // => 1
这里解释一下为什么互换会成功:
a = a ^ bb = a ^ b.基于1a被替换成a ^ b。因此,b = (a ^ b) ^ b = a ^ (b ^ b) = a ^ 0 = a.记住比b现在是a.a = a ^ b.基于1a被替换为a ^ b,基于2b被替换为a。因此,a = (a ^ b) ^ a = b ^ (a ^ a) = b ^ 0 = b。变量a变成b。
如果你觉得这个解释很复杂,可以跳过它。位数XOR(n ^ n = 0 和n ^ 0 = n)的属性由3个赋值组成,可以让你交换a 和b 的值。
使用位数XOR运算法则交换变量有局限性:你只能交换整数。
5.总结
JavaScript提供了许多交换变量的好方法,包括使用或不使用额外的内存。
第一种方法,我推荐用于日常使用,是通过应用结构化赋值来交换变量[a, b] = [b, a] 。这是一种简短而富有表现力的方法。
第二种方法是使用一个临时变量。这是对结构化赋值方法的一个很好的替代。
第三种方法,使用加法和减法,不使用额外的变量或内存。然而,该方法只限于交换整数。
以同样的方式,第四种使用位数XOR的方法也不使用额外的内存。但同样,你只能交换整数。
你喜欢用什么方法来交换变量?