代码技巧|变量交换方法
整理些代码小技巧和基础知识,为接下来要开的算法专栏做一些铺垫。
本篇主要分享常用的三种变量交换方法:临时变量交换、加减法交换、异或交换。
1.临时变量交换
交互流程
atmpb(1)把a的值copy给tmp临时变量(2)使用b的值更新a,此时a完成交换(3)再使用tmp的值(也就是a的原值)更新b,此时b也完成交换atmpb
代码示例
//临时变量交换
func TestExchange1(t *testing.T) {
a := 1
b := 2
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:1 , b:2
//(1)把a的值copy给tmp临时变量
tmp := a
//(2)使用b的值更新a,此时a完成交换
a = b
b = tmp
//(3)再使用tmp的值(也就是a的原值)更新b,此时b也完成交换
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:2 , b:1
}
讲解
- 依赖一个临时变量
tmp
完成a
和b
变量的置换 - 理解简单
2.加减法交换
交互流程
ab(1)将a和b相加,并赋值给a,此时a为a、b之和,此时a非彼时a,如果要区分可以标记为ab(2)将新a(即a、b之和)减去b(得到是原a的值),再赋值给b,就相当于让b更新为a的值,也就完成了b的交换(3)此时,b完成交换,此时b非彼时b,上一轮完成赋值后已经是a的值,因此,a减去b其实是ab之和减去a,真实结果值此时为b,于是用它来更新变量a,也就完成了a变量的交换ab
代码示例
//加减法交换
func TestExchange2(t *testing.T) {
a := 1
b := 2
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:1 , b:2
//(1)将a和b相加,并赋值给a,此时a为a、b之和,此时a非彼时a,如果要区分可以标记为ab
a = a + b
// (2) 将新a(即a、b之和)减去b(得到是原a的值),再赋值给b,就相当于让b更新为a的值,也就完成了b的交换
b = a - b
//(3)此时,b完成交换,此时b非彼时b,上一轮完成赋值后已经是a的值,因此,a减去b其实是ab之和减去a,真实结果值此时为b,于是用它来更新变量a,也就完成了a变量的交换
a = a - b
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:2 , b:1
}
讲解
- 优点是不需要引入新变量,可以基于原变量完成原地交换
- 缺点是存在数值越界溢出风险
3.异或交换
交互流程
a^bab(1)此时a、b二进制为:a=01、b=10,异或后为11,赋值给a,此时a非彼时a,可以标记为c(2)此时二进制为:a=11(即c)、b=10,异或后为01,赋值给b,此时b完成交换(3)此时二进制为:a=11(即c)、b=01,异或后为10,赋值给a,此时a完成交换a^bab
代码示例
//异或交换
func TestExchange3(t *testing.T) {
a := 1
b := 2
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:1 , b:2
//(1)此时a、b二进制为:a=01、b=10,异或后为11,赋值给a
a = a ^ b
//a:3 ,b:2
//(2)此时二进制为:a=11、b=10,异或后为01,赋值给b,此时b完成交换
b = a ^ b
//a:3 ,b:1
//(3)此时二进制为:a=11、b=01,异或后为10,赋值给a,此时a完成交换
a = a ^ b
fmt.Printf("a:%d ,b:%d\n", a, b)
//a:2 , b:1
}
讲解
- 利用异或交换律:
a^(b^c) = (a^b)^c
- 效率高
- 需要了解二进制异或规律的知识储备进行应用
转载自:https://juejin.cn/post/7216548158972166201