# 不用中间变量交换两个数

我们有长度为2的一个数组,我们想要交换这两个数的位置,如何使用中间变量,交换数组中的6和3呢?
根据二进制基础与位运算,我们可以知道6的二进制,3的二进制,并可以算出6^3的二进制。

# 算法步骤
基于以上我们开始使用位运算,交换数组两个位置的值。
- 我们重新赋值 数组的
0位置 = 数组的0位置 ^ 数组的1位置,即数组的0变为6^3,对应的十进制为5

我们重新赋值 数组的
1位置 = 数组的0位置 ^ 数组的1位置,即数组的1变为5^3,对应的十进制为6。此时我们最初的0位置的6来到了1位置。

我们重新赋值 数组的
0位置 = 数组的0位置 ^ 数组的1位置,即数组的0变为5^6,对应的十进制为3。此时我们最初的1位置的3来到了0位置。我们完成了数组两个位置值的交换,且没有使用中间变量。
# 代码实现
根据我们以上的不走不难写出,我们下面的算法代码:
func BinSwap(arr []int, i, j int) {
arr[i] = arr[i] ^ arr[j]
arr[j] = arr[i] ^ arr[j]
arr[i] = arr[i] ^ arr[j]
}
1
2
3
4
5
2
3
4
5
但是在go语言中,我们还可以直接使用以下的语法糖来交换数组内容的位置:
func GoSwap(arr []int, i, j int) {
arr[i], arr[j] = arr[j], arr[i]
}
1
2
3
2
3
这两种方式哪种速度快?于是我们写出如下的基准测试:
import "testing"
func BenchmarkBinSwap(b *testing.B) {
// 可以放初始化代码,时间过长,需要使用 b.ResetTimer()
// 可以放初始化代码,时间过长,需要使用 b.ResetTimer()
arr := []int{3, 6}
// 将计时器归零, 避免循环之前的初始化代码的干扰
// 排除初始化代码的影响,只测试循环内部的代码性能。
b.ResetTimer()
// loop b.N times
for i := 0; i < b.N; i++ {
// 待测试性能的函数
BinSwap(arr, 0, 1)
}
}
func BenchmarkGoSwap(b *testing.B) {
// 可以放初始化代码,时间过长,需要使用 b.ResetTimer()
// 可以放初始化代码,时间过长,需要使用 b.ResetTimer()
arr := []int{3, 6}
// 将计时器归零, 避免循环之前的初始化代码的干扰
// 排除初始化代码的影响,只测试循环内部的代码性能。
b.ResetTimer()
// loop b.N times
for i := 0; i < b.N; i++ {
// 待测试性能的函数
GoSwap(arr, 0, 1)
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
结果如下:

我们的算法交换数组位置的速度,并没有go语法糖的速度快,所以在go中我们可以直接使用语法糖交换位置,以上的算法就当做我们熟悉二进制的练习~